我有一个关于创建可与 v-model
一起使用的 VueJS 组件的问题,它利用底层 value
prop 和 $emit('input', newVal)
。
props: {
value: Array
},
methods: {
moveIdToIndex (id, newIndex) {
const newArrayHead = this.value
.slice(0, newIndex)
.filter(_id => _id !== id)
const newArrayTail = this.value
.slice(newIndex)
.filter(_id => _id !== id)
const newArray = [...newArrayHead, id, ...newArrayTail]
return this.updateArray(newArray)
},
updateArray (newArray) {
this.$emit('input', newArray)
}
}
在上面的代码示例中,如果我快速连续地进行两次修改,它们都会在“旧数组”(未修改的 value
属性)上执行。
moveIdToIndex('a', 4)
moveIdToIndex('b', 2)
换句话说,我需要等待 value
通过 $emit('input')
更新,以便第二次调用 moveIdToIndex
以使用已修改的数组。
错误的解决方案 1
一种解决方法是将 updateArray
更改为:
updateArray (newArray) {
return new Promise((resolve, reject) => {
this.$emit('input', newArray)
this.$nextTick(resolve)
})
}
然后像这样执行:
await moveIdToIndex('a', 4)
moveIdToIndex('b', 2)
但我不想这样做,因为我需要对一个 ID 数组执行此操作并将它们同时移动到不同的位置。而 await
ing 会大大降低性能。
错误的解决方案 2
我发现一个更好的解决方案是这样做:
updateArray (newArray) {
this.value = newArray
this.$emit('input', newArray)
}
然后我根本不需要等待 $emit
完成。
但是,在这种情况下,VueJS 会给出一个控制台错误:
Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "value"
有没有人有更好的解决方案?
最佳答案
好的。据我了解您的用例和应用程序,这些是您的选择。
首先,不要改变 props 直接在内部保存 props 然后修改那个值。
props: {
value: Array
},
data() {
return {
val: this.value
}
}
如果对数组的下一次修改依赖于对数组的先前修改,则您不能同时执行它们。但是你需要它发生得相当快(我假设你希望用户觉得它发生得很快)。您可以做的是对组件内的 val
进行修改,而不是使其依赖于 prop。 val
变量仅在安装组件时初始化。通过这种方式,您可以在 UI 中即时修改数据,并让数据库在后台更新。
换句话说,您的完整解决方案如下所示:
props: {
value: Array
},
data () {
return {val: this.value}
},
methods: {
moveIdToIndex (id, newIndex) {
const newArrayHead = this.val
.slice(0, newIndex)
.filter(_id => _id !== id)
const newArrayTail = this.val
.slice(newIndex)
.filter(_id => _id !== id)
const newArray = [...newArrayHead, id, ...newArrayTail]
return this.updateArray(newArray)
},
updateArray (newArray) {
this.val = newArray
this.$emit('input', newArray)
}
}
此解决方案解决了您的问题,并允许您快速连续执行 moveIdToIndex
,而无需等待任何事情。
现在,如果数组在应用程序中的许多地方使用,下一个最好的办法是将它移动到商店并将其用作单一事实点并更新它并使用它来更新您的组件。您的状态将不会同时快速更新,然后将更新延迟到数据库适当的时间。
关于javascript - 如何在 'value' 输入之前修改 VueJS 中的 `$emit(' prop')`完成更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55914130/