Vue.js2 - Object.assign({}, this.var) 防止监视方法
Vue.js2 - Object.assign({}, this.var) preventing watch method
returning this.user(全局计算的 属性)按预期工作。当然,我正在制作副本,因为我不想覆盖实际的用户数据。所以,我正在使用 Object.assign。但是,一旦我包含 return Object.assign({}, this.user)(相对于 this.user),watch 方法就不再起作用。
这是我的模板(我正在使用 bootstrap-vue):
<template>
<form role="form">
<b-form-group
label="First Name"
label-for="basicName"
:label-cols="3"
:horizontal="true">
<b-form-input id="user-name-first" type="text" v-model="userFormData.fname"></b-form-input>
</b-form-group>
<b-form-group
label="Last Name"
label-for="basicName"
:label-cols="3"
:horizontal="true">
<b-form-input id="user-name-lirst" type="text" v-model="userFormData.lname"></b-form-input>
</b-form-group>
<b-form-group
label="Email"
label-for="user-email"
:label-cols="3"
:horizontal="true">
<b-form-input id="user-email" type="text" v-model="userFormData.email"></b-form-input>
</b-form-group>
<b-form-group
:label-cols="3"
:horizontal="true">
<b-button type="submit" variant="primary">Save changes</b-button>
<b-button type="button" variant="secondary" @click="userFormCancel">Cancel</b-button>
</b-form-group>
</form>
</template>
因此,每当对 userProfile 应用更改时,它就会将 editsPending 设置为 true (通过输入上的 v-model)
<script>
export default {
name: 'userProfile',
data () {
return {
editsPending: false
}
},
computed: {
userFormData: function () {
return this.user
}
},
watch: {
userFormData: {
deep: true,
handler (val) {
this.editsPending = true
}
}
},
methods: {
userFormCancel () {
this.editsPending = false
}
}
}
</script>
...但这不是; userFormData 成为 user 的克隆,但 editsPending 不受 userFormData 更新的影响。
<script>
export default {
name: 'userProfile',
data () {
return {
editsPending: false
}
},
computed: {
userFormData: function () {
return Object.assign({}, this.user)
}
},
watch: {
userFormData: {
deep: true,
handler (val) {
this.editsPending = true
}
}
},
methods: {
userFormCancel () {
this.editsPending = false
}
}
}
</script>
任何人都可以解释为什么会发生这种情况并提出可行的解决方案吗?
测试了不同的东西来重现您看到的行为。
我怀疑您在模板中将输入绑定到 UserFormdata
(不正确)
<input v-model="userFormData.name">
而不是(正确)
<input v-model="user.name">
如果您能分享您的模板会有帮助;)
编辑:添加模板后。
new Vue({
el: '#app',
data () {
return {
editsPending: false,
user: { name: 'John Doe' },
userCachedData: {},
}
},
created() {
this.userCachedData = Object.assign({}, this.user);
},
watch: {
user: {
deep: true,
handler (val) {
this.editsPending = true
}
}
},
methods: {
userFormCancel () {
this.editsPending = false
}
}
})
<div id="app">
{{ user }}
{{ userCachedData }}
<br>
<input v-model="user.name" />
{{ this.editsPending }}
</div>
代码笔:https://codepen.io/aurelien-bottazini/pen/BVNJaG?editors=1010
A computed property will only re-evaluate when some of its
dependencies have changed. (source)
这就是为什么它适用于 return this.user
而不是 Object.assign
的原因,因为它不是反应性依赖项。
如果您想要响应式数据,您应该将 userFormData
初始化为一个空对象数据,并在创建 Vue 实例时分配您的用户:
data () {
return {
editsPending: false,
userFormData: {}
}
},
created() {
this.userFormData = Object.assign({}, this.user)
},
您可以使用 $emit 为对象赋值:
mounted() {
this.$emit("userFormData", this.user);
}
returning this.user(全局计算的 属性)按预期工作。当然,我正在制作副本,因为我不想覆盖实际的用户数据。所以,我正在使用 Object.assign。但是,一旦我包含 return Object.assign({}, this.user)(相对于 this.user),watch 方法就不再起作用。
这是我的模板(我正在使用 bootstrap-vue):
<template>
<form role="form">
<b-form-group
label="First Name"
label-for="basicName"
:label-cols="3"
:horizontal="true">
<b-form-input id="user-name-first" type="text" v-model="userFormData.fname"></b-form-input>
</b-form-group>
<b-form-group
label="Last Name"
label-for="basicName"
:label-cols="3"
:horizontal="true">
<b-form-input id="user-name-lirst" type="text" v-model="userFormData.lname"></b-form-input>
</b-form-group>
<b-form-group
label="Email"
label-for="user-email"
:label-cols="3"
:horizontal="true">
<b-form-input id="user-email" type="text" v-model="userFormData.email"></b-form-input>
</b-form-group>
<b-form-group
:label-cols="3"
:horizontal="true">
<b-button type="submit" variant="primary">Save changes</b-button>
<b-button type="button" variant="secondary" @click="userFormCancel">Cancel</b-button>
</b-form-group>
</form>
</template>
因此,每当对 userProfile 应用更改时,它就会将 editsPending 设置为 true (通过输入上的 v-model)
<script>
export default {
name: 'userProfile',
data () {
return {
editsPending: false
}
},
computed: {
userFormData: function () {
return this.user
}
},
watch: {
userFormData: {
deep: true,
handler (val) {
this.editsPending = true
}
}
},
methods: {
userFormCancel () {
this.editsPending = false
}
}
}
</script>
...但这不是; userFormData 成为 user 的克隆,但 editsPending 不受 userFormData 更新的影响。
<script>
export default {
name: 'userProfile',
data () {
return {
editsPending: false
}
},
computed: {
userFormData: function () {
return Object.assign({}, this.user)
}
},
watch: {
userFormData: {
deep: true,
handler (val) {
this.editsPending = true
}
}
},
methods: {
userFormCancel () {
this.editsPending = false
}
}
}
</script>
任何人都可以解释为什么会发生这种情况并提出可行的解决方案吗?
测试了不同的东西来重现您看到的行为。
我怀疑您在模板中将输入绑定到 UserFormdata
(不正确)
<input v-model="userFormData.name">
而不是(正确)
<input v-model="user.name">
如果您能分享您的模板会有帮助;)
编辑:添加模板后。
new Vue({
el: '#app',
data () {
return {
editsPending: false,
user: { name: 'John Doe' },
userCachedData: {},
}
},
created() {
this.userCachedData = Object.assign({}, this.user);
},
watch: {
user: {
deep: true,
handler (val) {
this.editsPending = true
}
}
},
methods: {
userFormCancel () {
this.editsPending = false
}
}
})
<div id="app">
{{ user }}
{{ userCachedData }}
<br>
<input v-model="user.name" />
{{ this.editsPending }}
</div>
代码笔:https://codepen.io/aurelien-bottazini/pen/BVNJaG?editors=1010
A computed property will only re-evaluate when some of its dependencies have changed. (source)
这就是为什么它适用于 return this.user
而不是 Object.assign
的原因,因为它不是反应性依赖项。
如果您想要响应式数据,您应该将 userFormData
初始化为一个空对象数据,并在创建 Vue 实例时分配您的用户:
data () {
return {
editsPending: false,
userFormData: {}
}
},
created() {
this.userFormData = Object.assign({}, this.user)
},
您可以使用 $emit 为对象赋值:
mounted() {
this.$emit("userFormData", this.user);
}