我有一个名为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岁。
我有一个应用程序,我正在尝试观察人员数组,当任何值发生更改时,然后记录更改:
<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中,结果是一个空数组,而不是我所期望的更改后的对象。
如果有人能建议为什么会发生这种情况,或者我在这里做错了什么,那么我将非常感激,非常感谢!
发布于 2016-12-14 13:41:49
您的旧值和新值之间的比较函数有一些问题。最好不要把事情搞得太复杂,因为这会增加您以后的调试工作。你应该让它保持简单。
最好的方法是创建一个person-component
,并在它自己的组件中单独监视每个人,如下所示:
<person-component :person="person" v-for="person in people"></person-component>
请在下面找到观看inside person组件的工作示例。如果您想在父端处理,可以使用$emit
向上发送一个事件,包含修改后的person的id
。
Vue.component('person-component', {
props: ["person"],
template: `
<div class="person">
{{person.name}}
<input type='text' v-model='person.age'/>
</div>`,
watch: {
person: {
handler: function(newValue) {
console.log("Person with ID:" + newValue.id + " modified")
console.log("New age: " + newValue.age)
},
deep: true
}
}
});
new Vue({
el: '#app',
data: {
people: [
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 32},
{id: 2, name: 'Joe', age: 38}
]
}
});
<script src="https://unpkg.com/vue@2.1.5/dist/vue.js"></script>
<body>
<div id="app">
<p>List of people:</p>
<person-component :person="person" v-for="person in people"></person-component>
</div>
</body>
发布于 2016-12-14 14:31:22
这是一个定义良好的行为。不能获取变异对象的旧值。这是因为newVal
和oldVal
都引用了同一个对象。Vue不会保留您变异的对象的旧副本。
如果您用另一个对象替换了该对象,Vue将为您提供正确的引用。
阅读docs. (vm.$watch
)中的Note
部分
发布于 2016-12-14 15:26:34
我已经更改了它的实现来解决您的问题,我创建了一个对象来跟踪旧的更改并将其与之进行比较。你可以用它来解决你的问题。
这里我创建了一个方法,在这个方法中,旧值将存储在一个单独的变量中,然后将在监视中使用。
new Vue({
methods: {
setValue: function() {
this.$data.oldPeople = _.cloneDeep(this.$data.people);
},
},
mounted() {
this.setValue();
},
el: '#app',
data: {
people: [
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 32},
{id: 2, name: 'Joe', age: 38}
],
oldPeople: []
},
watch: {
people: {
handler: function (after, before) {
// Return the object that changed
var vm = this;
let changed = after.filter( function( p, idx ) {
return Object.keys(p).some( function( prop ) {
return p[prop] !== vm.$data.oldPeople[idx][prop];
})
})
// Log it
vm.setValue();
console.log(changed)
},
deep: true,
}
}
})
请参阅更新后的
https://stackoverflow.com/questions/41135188
复制相似问题