VueJS在不改变父数据​​的情况下编辑道具的正确方法

use*_*266 11 javascript laravel vue.js

在我的父vue组件中,我有一个user对象.

如果我将该用户对象作为prop传递给子组件:

<child :user="user"></child>
Run Code Online (Sandbox Code Playgroud)

在我更新的子组件中user.name,它也会在父组件中更新.

我想编辑子组件中的用户对象,而不会在父组件中的用户对象中反映更改.

有没有更好的方式来实现这一目标不是与克隆对象:JSON.parse(JSON.stringify(obj))

Ber*_*ert 21

您不必使用该JSON对象.

const child = {
  props:["user"],
  data(){
    return {
      localUser: Object.assign({}, this.user)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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)
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

因为我决定使用用户的本地副本,@ user3743266是正确的,所以组件不会自动更新.该属性 user已更新,但未更新localUser.在这种情况下,如果您希望在属性更改时自动更新本地数据,则需要一个观察程序.

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)
    }
  }
})
Run Code Online (Sandbox Code Playgroud)

这是更新的小提琴.

这使您可以完全控制何时/是否更新或发出本地数据.例如,您可能希望在更新本地状态之前检查条件.

  watch:{
    user(newUser){
      if (condition)
        this.localUser = Object.assign({}, newUser)
    }
  }
Run Code Online (Sandbox Code Playgroud)

正如我在其他地方所说的,有时您可能希望利用可变的对象属性,但也有时候您可能需要更多控制.

  • 你确定吗?我会说这个线程和你的答案有很多价值。像这样的问题可能与每个使用 vue 的人相关。离开它,它可能会有一个漫长而令人惊讶的生命。 (2认同)
  • `Object.assign`不会深层复制整个对象(只是它看起来的第一层).因此,像`object.key1.key2`这样的嵌套属性将在父级和子级中都发生变化.解决它的方法是使用`localUser:JSON.parse(JSON.stringify(this.user))` (2认同)