在Vue.js中创建传递props的子组件的本地副本?

20

在Vue.js中,如何编辑prop而不更改父级数据?这是什么意思呢?就是说,当我们在Vue.js中从父组件传递任何属性到子组件时,如果我们在子组件中对该属性进行任何更改,则该更改也会反映在父组件中。

在Vue.js中是否有一种方法可以在子组件中制作传递属性的本地副本?

我搜索了一下,但无论在哪里都写着我们可以通过以下方式来实现这一点。

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

这里将对象传递给用户,并在本地创建其副本,但根本不起作用,本地用户未定义。

您是否遇到过这样的情况:需要更改子组件中父级属性而不影响父组件状态,即在子组件中制作自己的副本并进行编辑?

对此有任何见解都将很有帮助。

我还在某个地方读到,在vue@2.3.3中,当我们想从父组件传递prop到子组件时,需要手动创建本地数据以保存prop,这会产生大量无用的工作。

我们可以像这样手动创建本地数据:

props: ['initialCounter'],
data: function () {
    return { counter: this.initialCounter }
}

但是在我的情况下这并不起作用。 我正在使用vue cli 3.0.1进行开发。

这是相同代码:

在我的应用程序中,我有一个列表视图。

enter image description here

当用户单击 See Focused View 按钮时,用户将被重定向到下面提到的视图,即实际上是引导 - 模态视图。

enter image description here

在这里,用户可以编辑名称的值,但是因为我从父组件传递名称作为属性,所以在此处对其进行编辑会导致在父组件中也更新,即在列表视图中也更新。


@tony19 你可以关注这个代码片段,以便更方便地访问 - https://codesandbox.io/s/j4n13vxw6w - Divyanshu Rawat
1个回答

32
在你的fiddle中,子组件使用Object.assign()来创建一个包含对象数组的data的副本。然而,这只会创建一个浅拷贝,因此数组元素仍然会引用原始实例,导致你看到的行为。
深复制数组的几种解决方案:
  • Use JSON.parse(JSON.stringify(this.data)), which works reasonably well for primitive object properties (String, Number, BigInt, Boolean, undefined, and null):

    data() {
      return {
        local_data: JSON.parse(JSON.stringify(this.data))
      }
    }
    

    (demo 1)

  • Map the objects into new ones, which works well if the depth is only 1 (nested arrays/objects will still be shallow copied):

    data() {
      return {
        local_data: this.data.map(x => ({...x}))
      }
    }
    

    (demo 2)

  • Use a utility library, such as lodash's cloneDeep:

    data() {
      return {
        local_data: _.cloneDeep(this.data)
      }
    }
    

    (demo 3)


3
这是我在苦思冥想了几个小时后需要的很好的解释。 - Chase Ernst
这非常有帮助,我喜欢多个示例。Demo 1中的数组中的日期对象是否存在任何问题? - Caine Nielsen
1
@CaineNielsen JSON.stringify 会将 Date 对象转换为字符串(通过 Date#toString),因此它们需要在 JSON.parse 中进行 恢复 - tony19
这个克隆的操作仍然感觉有些笨拙。难道真的没有比克隆对象更好的解决方案吗? - Walnussbär
@Walnussbär 在JavaScript中,对象是通过引用传递的,因此克隆是将原始引用与新对象分离的唯一方法(截至2023年...也许语言在未来会发生变化)。 - tony19
我知道,但每次我必须这样做时,感觉都不好,就像是一个很大的负担。但是没办法,为了规避这个问题,语言确实需要改变。 - Walnussbär

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接