避免直接改变道具...但这似乎是官方示例所做的事情?

art*_*bot 4 javascript vue.js vuejs2

我正在编写一个递归树渲染器,并遭受“避免直接更改道具”警告。

据我了解,“道具减少,事件增加”意味着孩子不能/不应直接更改父数据。我可以通过编写很多代码来避免此错误,在这些代码中,一个组件$emit发生更改,其父组件捕获并重新发出该组件,然后不断执行,直到顶层组件最终可以更改数据,然后再通过树。虽然我得到了一个通用组件需要与其父组件无关的用例,但对于递归组件而言,它似乎效率极低。

我注意到提供了官方的VueJs 2 树视图示例。但是查看该代码显示,子组件被传递了属于父组件的对象,但是子组件仍被允许直接对其进行更新(例如,在addChild或changeType方法中)。

我对jsfiddle做了一个变体作为证明。我所做的所有更改都是将父级的数据输出为json,以便您可以看到它已更改。一开始看起来像这样:

{"name":"My Tree","children":[{"name":"hello"},{"name":"wat"}
Run Code Online (Sandbox Code Playgroud)

然后,如果您单击第一个父级,然后双击1. hello触发,changeType您将注意到父级的数据现在已更改:

{"name":"My Tree","children":[{"name":"hello","children":[{"name":"new stuff"}]},{"name":"wat"}... 
Run Code Online (Sandbox Code Playgroud)

...但是没有触发可怕的“避免直接改变道具”警告。

因此,我显然缺少一些细微差别。令人沮丧的是,对此有太多问题,我担心添加重复项。但是我觉得这是不同的,因为我在问“为什么给出的示例直接改变道具”?

Ber*_*ert 5

对象和数组通过引用传递,因此可以完全改变对象的属性或作为道具添加的数组内容,因为这不会更改引用。对对象属性的更改将在使用特定引用的任何地方反映出来。官方文档中对此进行了说明

请注意,JavaScript中的对象和数组是通过引用传递的,因此,如果prop是数组或对象,则在子对象内部对对象或数组本身进行更改将影响父状态。

如果您尝试将作为属性传入的对象设置为完全不同的对象,则警告将显示在控制台中。

是否选择利用这一点是设计考虑因素。在Vue树示例中,代码使对象属性发生突变,并且更改将在所有地方反映出来。一个反例可能是编辑用户。如果您有一个User组件,并且希望对该对象所做的更改在更改被视为有效后才反映在该组件外部(以允许取消更改),则应制作该对象的内部副本,编辑副本并发出被视为可接受的更改。