我有一个名为people
的数组,其中包含如下对象:
- 之前**
[
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 32},
{id: 2, name: 'Joe', age: 38}
]
它可以改变:
- 之后**
[
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 33},
{id: 2, name: 'Joe', age: 38}
]
注意弗兰克刚满33岁。
我有一个应用程序,我尝试在其中观察people数组,并在任何值发生变化时记录变化:
<style>
input {
display: block;
}
</style>
<div id="app">
<input type="text" v-for="(person, index) in people" v-model="people[index].age" />
</div>
<script>
new Vue({
el: '#app',
data: {
people: [
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 32},
{id: 2, name: 'Joe', age: 38}
]
},
watch: {
people: {
handler: function (val, oldVal) {
// Return the object that changed
var changed = val.filter( function( p, idx ) {
return Object.keys(p).some( function( prop ) {
return p[prop] !== oldVal[idx][prop];
})
})
// Log it
console.log(changed)
},
deep: true
}
}
})
</script>
我基于question that I asked yesterday中关于数组比较的内容,选择了最快的工作答案。
因此,在这一点上,我希望看到以下结果:{ id: 1, name: 'Frank', age: 33 }
但我在控制台中得到的是(记住我在一个组件中有它):
[Vue warn]: Error in watcher "people"
(found in anonymous component - use the "name" option for better debugging messages.)
在codepen that I made中,结果是一个空数组,而不是我所期望的更改对象。
如果任何人可以建议为什么会发生这种情况或我在这里出了问题,那么它将是非常感谢,非常感谢!
7条答案
按热度按时间tsm1rwdh1#
你的新旧值比较函数有问题。最好不要把事情弄得太复杂,因为这会增加你以后的调试工作量。你应该保持简单。
最好的方法是创建一个
person-component
,并在它自己的组件中分别观察每个人,如下所示:下面是一个观察内部人员组件的工作示例。如果您想在父端处理它,可以使用
$emit
向上发送一个事件,包含修改人员的id
。x一个一个一个一个x一个一个二个x
ymdaylpp2#
我已经改变了它的实现来解决你的问题,我做了一个对象来跟踪旧的变化并与之比较,你可以用它来解决你的问题。
这里我创建了一个方法,其中旧值将存储在一个单独的变量和中,然后将在手表中使用。
请参阅更新的codepen
zdwk9cvp3#
这是一个定义良好的行为。你不能得到一个 mutated 对象的旧值。这是因为
newVal
和oldVal
引用了同一个对象。Vue将 * 不会 * 保留一个你mutated的对象的旧副本。如果您用另一个对象“替换”了该对象,Vue将为您提供正确的引用。
阅读文档中的
Note
部分。(vm.$watch
)有关here和here的更多信息。
3j86kqsm4#
组件解决方案和深度克隆解决方案各有优势,但也存在问题:
1.有时候,您需要跟踪抽象数据中的更改-围绕这些数据构建组件并不总是有意义的。
1.每次进行更改时深度克隆整个数据结构可能会非常昂贵。
我认为有一个更好的方法,如果你想观察列表中的所有项目,并知道列表中的哪个项目发生了变化,你可以分别为每个项目设置自定义观察器,如下所示:
使用这个结构,
handleChange()
将接收更改的特定列表项-从那里您可以执行任何您喜欢的处理。我还编写了一个more complex scenario here文档,以防您向列表添加/删除项目(而不仅仅是操作已经存在的项目)。
zlwx9yxi5#
这是我用来深度观察对象的工具,我的要求是观察对象的子字段。
z31licg06#
如果我们有对象或对象数组,并希望在Vuejs或NUXTJS中查看它们,则需要在watch中使用
deep: true
zvms9eto7#
我用“计算”代替“观察”解决了这个问题!
我还没有测试过这段代码,但我认为它应该可以工作。如果没有,请在评论中告诉我。