在我的父vue组件中,我有一个user
对象。
如果我将该用户对象作为prop传递给子组件:
<child :user="user"></child>
在我的子组件中我更新user.name
,它也将在父级中更新。
我想编辑子组件中的用户对象,而不会在父组件中的用户对象中反映更改。
是否有更好的方法来实现此目的,而不是克隆对象:JSON.parse(JSON.stringify(obj))
?
答案 0 :(得分:18)
您不必使用JSON
对象。
const child = {
props:["user"],
data(){
return {
localUser: Object.assign({}, this.user)
}
}
}
在您孩子的内部使用localUser
(或任何您想要的名称)。
修改强>
我修改了为这个问题的另一个答案创建的小提琴,以演示上述概念和@ user3743266问
我自己也要抓住这个,而且我发现了这一点 有用。你的例子效果很好。在孩子身上,你创造了一个 数据中的元素,其中包含prop的副本,并且子项工作 与副本。有趣和有用,但......我不清楚 当本地副本更新时,如果其他东西修改了 家长。我修改你的小提琴,删除v-ifs所以一切都是 可见,并复制编辑组件。如果您在一个中修改名称 组件,另一个是孤立的,没有变化?
当前组件如下所示:
Vue.component('edit-user', {
template: `
<div>
<input type="text" v-model="localUser.name">
<button @click="$emit('save', localUser)">Save</button>
<button @click="$emit('cancel')">Cancel</button>
</div>
`,
props: ['user'],
data() {
return {
localUser: Object.assign({}, this.user)
}
}
})
因为我决定使用用户的本地副本,@ user3743266是正确的,所以组件不会自动更新。 属性 user
已更新,但localUser
未更新。在这种情况下,只要属性发生变化, if 就会自动更新本地数据,您需要一个观察者。
Vue.component('edit-user', {
template: `
<div>
<input type="text" v-model="localUser.name">
<button @click="$emit('save', localUser)">Save</button>
<button @click="$emit('cancel')">Cancel</button>
</div>
`,
props: ['user'],
data() {
return {
localUser: Object.assign({}, this.user)
}
},
watch:{
user(newUser){
this.localUser = Object.assign({}, newUser)
}
}
})
以下是更新后的fiddle。
这使您可以完全控制何时/是否更新或发出本地数据。例如,您可能希望在更新本地状态之前检查条件。
watch:{
user(newUser){
if (condition)
this.localUser = Object.assign({}, newUser)
}
}
正如我在其他地方所说的那样,有时您可能希望利用对象属性是可变的,但也有一些时候您可能想要更多控制。
答案 1 :(得分:0)
According to this,孩子&#34;可以&#34;#34;并且&#34;不应该&#34;#34;修改父母的数据。但是here你可以看到,如果父母将一些被动数据作为属性传递给孩子,那么它会通过引用进行传递,父母会看到孩子的变化。这可能是你大多数时候想要的,不是吗?您只修改了父显式共享的数据。如果您希望孩子拥有user
的独立副本,您可以使用JSON.parse(JSON.stringify())执行此操作,但要注意您将序列化Vue注入的属性。你什么时候做的?记住道具是被动的,所以父母可以随时发送一个新用户,消除局部变化吗?
也许您需要告诉我们更多关于您希望孩子拥有自己副本的原因?孩子与副本有什么关系?如果孩子的用户以某种系统的方式从父用户派生(大写所有文本或其他内容),请查看计算属性。
答案 2 :(得分:0)
您可以使用您想要在本地编辑的信息创建数据变量,并在创建的方法中加载值
data() {
return { localUserData: {name: '', (...)}
}
(...)
created() {
this.localUserData.name = this.user.name;
}
通过这种方式,您可以清楚地了解要编辑的数据。根据需要,您可能希望有一个观察者在用户道具发生变化时更新localData。
答案 3 :(得分:0)
在上述解决方案中,观察者不会在第一次绑定时触发,仅在更改道具时触发。要解决此问题,请使用Instant = true
watch: {
test: {
immediate: true,
handler(newVal, oldVal) {
console.log(newVal, oldVal)
},
},
}