我理解这个概念: child 在自己的 Prop 数据副本上工作,当它被改变时,它可以 $emit
这种变化,所以 parent 可以更新自己。
但是,我正在处理递归树结构,例如文件系统,是一个很好的类比。
[
{ type: 'dir', name: 'music', children: [
{ type: 'dir', name: 'genres', children: [
{ type: 'dir', name: 'triphop', children: [
{ type: 'file', name: 'Portishead' },
...
]},
]}
]}
]}
我有一个名为
Thing
的递归组件这需要 childtree
Prop 看起来有点像这样:<template>
<input v-model="tree.name" />
<thing v-for="childtree in tree.children" :tree="childtree" ></thing>
</template>
修改名字显然是要直接修改prop,这是要避免的,Vue会发出警告。
但是,我能看到避免这种情况的唯一方法是让每个组件对
childtree
进行深层复制。 ;然后 $emit
一份我们的副本,并有一个 @input
(或类似的)将其复制回原件;一直向上爬到树上,然后沿着树向下一直更改 Prop ,从而导致所有内容的另一个深拷贝!感觉就像它在任何大小的树上都会非常低效。
有没有更好的办法?我知道你可以欺骗 Vue 不发出错误/警告 example jsfiddle .
最佳答案
解决您的问题的方法是仅从子组件传递事件。
https://jsfiddle.net/kv1w72pg/2/
<input @input="(e) => $emit('input', e.target.value)" />
话虽如此,我强烈建议您使用其他解决方案,例如:
它将使代码清晰并确保一个事实来源。
编辑:在递归继承的情况下,使用提供注入(inject)会更容易:https://jsfiddle.net/s0b9fpr8/4/
通过这种方式,您可以提供一个函数,可以将基础组件的状态更改为所有子组件(必须注入(inject)函数)。
关于javascript - 如何在递归组件中出现 "Avoid mutating a prop directly",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60672605/