【发布时间】:2022-01-02 09:09:24
【问题描述】:
我从事 Vue 2 项目已经有一段时间了,在升级我们的 linting 要求后,我发现我们的许多子组件中都有 prop 突变错误。在我们的项目中,我们将一个单例对象作为道具传递给许多组件,并且最初是直接从子组件更新对象。 Vue seems to suggest using the v-bind.sync feature 用于从子组件更新 props(或使用等效的 v-bind 和 v-on)。但是,这并不能解决 数组中的嵌套组件修改prop 的问题。
以这个使用prop突变的(伪)代码为例:
注意:假设const sharedObject: { arrayElements: Array<{ isSelected: boolean }> } = ...
Page.vue
<template>
...
<Component1 :input1="sharedObject" />
...
</template>
Component1.vue
<template>
...
<template v-for="elem in sharedObject.arrayElements">
<Component2 :input2="elem" />
</template>
...
</template>
Component2.vue
<template>
...
<q-btn @click="input2.isSelected = !input2.isSelected"></q-btn>
...
</template>
在 Vue 2 中从嵌套组件更新 input2.isSelected 之类的属性的正确方法是什么?我想到的所有方法都有缺陷。
有缺陷的方法
我相信我们想冒泡一下input2.isSelected 已在Component2 中修改为Page.vue,但是,这似乎要么导致代码混乱,要么让人感到不安我们只是以迂回的方式抑制掉毛错误。
为了演示“乱码”方法,首先注意Page.vue 不知道elem 在sharedObject.arrayElements 中的索引。因此,我们需要从Component1 向Page.vue 发出一个对象,其中包含input2.isSelected 的状态以及sharedObject.arrayElements 中elem 的索引。这很快就会变得混乱。那我们有的例子呢:
Component1.vue
<template>
...
<template v-for="elem in sharedObject.arrayElements">
<template v-for="elem2 in elem.arrayElements">
<Component2 :input2="elem2" />
</template>
</template>
...
</template>
在这种情况下,我们可能需要传递 2 个索引!对我来说,这似乎不是一个可持续的解决方案。
我想到的替代方法是回调函数(通过组件层次结构作为道具传递),它将我们要更新的元素和包含我们要更新的属性的对象作为输入(使用Object.assign) .
这让我非常感到不安,因为我不知道我们不能从子组件更新传递引用属性的真正原因。对我来说,这似乎只是在没有 linter 注意到的情况下更新从 Component2 传入的一种迂回方式。如果道具在传递给子组件时发生了一些神奇的修改,那么肯定会将我在Component2 中收到的对象传递给回调函数并在父组件中对其进行修改基本上只是更新道具在子组件中,但更复杂。
在 Vue 2 中解决此问题的正确方法是什么?
【问题讨论】:
标签: javascript vue.js vuejs2 vue-component quasar-framework