VueJS编辑道具的正确方法,无需更改父数据

时间:2017-06-27 22:20:38

标签: javascript laravel vue.js

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

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

<child :user="user"></child>

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

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

是否有更好的方法来实现此目的,而不是克隆对象:JSON.parse(JSON.stringify(obj))

4 个答案:

答案 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)
    },
  },
}