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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44790842/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 16:13:29  来源:igfitidea点击:

VueJS right way to edit prop without changing parent data

javascriptlaravelvue.js

提问by user3743266

In my parent vue component I have a userobject.

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

If I pass that user object to a child component as a prop:

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

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

and in my child component I update user.name, it will get updated in the parent as well.

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

I want to edit the user object in child component without the changes being reflected in the user object that is in parent component.

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

Is there a better way to achieve this than cloning the object with: JSON.parse(JSON.stringify(obj))?

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

回答by Bert

You don't have to use the JSONobject.

您不必使用该JSON对象。

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

Use localUser(or whatever you want to call it) inside your child.

localUser在您的孩子体内使用(或任何您想称呼的方法)。

Edit

编辑

I had modified a fiddle created for another answer to this question to demonstrate the above concept and @user3743266 asked

我已经修改了为这个问题的另一个答案创建的小提琴来演示上述概念,@user3743266 问

I'm coming to grips with this myself, and I'm finding this very useful. Your example works well. In the child, you've created an element in data that takes a copy of the prop, and the child works with the copy. Interesting and useful, but... it's not clear to me when the local copy gets updated if something else modifies the parent. I modified your fiddle, removing the v-ifs so everything is visible, and duplicating the edit component. If you modify name in one component, the other is orphaned and gets no changes?

我自己正在解决这个问题,我发现这非常有用。你的例子效果很好。在子元素中,您在 data 中创建了一个元素,该元素获取道具的副本,并且子元素使用该副本。有趣且有用,但是......如果其他内容修改了父级,我不清楚本地副本何时更新。我修改了你的小提琴,删除了 v-ifs,所以一切都可见,并复制了编辑组件。如果您修改一个组件中的名称,另一个组件将成为孤立的并且没有任何更改?

The current component looks like this:

当前组件如下所示:

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)
    }
  }
})

Because I made the design decision to use a local copyof the user, @user3743266 is correct, the component is not automatically updated. The propertyuseris updated, but localUseris not. In this case, ifyou wanted to automatically update local data whenever the property changed, you would need a watcher.

因为我的设计决定使用用户的本地副本,@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)
    }
  }
})

Here is the updated fiddle.

这是更新的小提琴

This allows you full control over when/if the local data is updated or emitted. For example, you might want to check a condition before updating the local state.

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

  watch:{
    user(newUser){
      if (condition)
        this.localUser = Object.assign({}, newUser)
    }
  }

As I said elsewhere, there are times when you might want to take advantage of objects properties being mutable, but there are also times like this where you might want more control.

正如我在别处所说的,有时您可能希望利用可变的对象属性,但有时您可能需要更多控制。

回答by Botea Florin

in the above solutions, the watcher won't trigger at first binding, only at prop change. To solve this, use immediate=true

在上述解决方案中,观察者不会在第一次绑定时触发,只会在道具更改时触发。为了解决这个问题,使用immediate=true

watch: {
  test: {
    immediate: true,
    handler(newVal, oldVal) {
      console.log(newVal, oldVal)
    },
  },
}

回答by bbsimonbb

According to this, children "can't" and "shouldn't" modify the data of their parents. But hereyou can see that if a parent passes some reactive data as a property to a child, it's pass-by-reference and the parent sees the child's changes. This is probably what you want most of the time, no? You're only modifying the data the parent has explicitly shared. If you want the child to have an independent copy of user, you could maybe do this with JSON.parse(JSON.stringify()) but beware you'll be serializing Vue-injected properties. When would you do it? Remember props are reactive, so the parent could send down a new user at any time, wiping out local changes?

据此,孩子“不能”“不应该”修改父母的数据。但是在这里您可以看到,如果父级将一些反应性数据作为属性传递给子级,则它是通过引用传递的,父级会看到子级的更改。这可能是您大多数时候想要的,不是吗?您只是在修改父级明确共享的数据。如果您希望孩子拥有 的独立副本user,您可以使用 JSON.parse(JSON.stringify()) 执行此操作,但要注意您将序列化 Vue 注入的属性。你什么时候做?还记得 props 是被动的,所以父级可以随时发送一个新用户,消除本地更改吗?

Perhaps you need to tell us more about why you want the child to have it's own copy? What is the child going to do with its copy? If the child's user is derived from the parent user in some systematic way (uppercasing all text or something), have a look at computed properties.

也许您需要告诉我们更多关于为什么您希望孩子拥有自己的副本?孩子将如何处理它的副本?如果孩子的用户是以某种系统的方式从父用户派生的(大写所有文本或其他内容),请查看计算属性。

回答by Victor Mikó

you can have a data variable just with the information you want to be locally editable and load the value in the created method

您可以拥有一个仅包含您希望在本地可编辑的信息的数据变量,并在创建的方法中加载该值

data() {
return { localUserData: {name: '', (...)}
}
(...)
created() {
    this.localUserData.name = this.user.name;
}

This way you keep it clear of which data you are editing. Depending on the need, you may want to have a watcher to update the localData in case the user prop changes.

这样您就可以清楚地了解您正在编辑哪些数据。根据需要,您可能希望有一个观察者来更新 localData,以防用户 prop 发生变化。