Vue-객체 배열을 깊이 관찰하고 변화를 계산합니까?
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}
]
Frank가 방금 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>
어제 어레이 비교에 대해 물어 본 질문을 기반으로 가장 빠른 응답을 선택했습니다.
따라서이 시점에서 다음과 같은 결과를 기대합니다. { id: 1, name: 'Frank', age: 33 }
그러나 내가 콘솔로 돌아가는 것은 (구성 요소에 있음을 염두에두고) 다음과 같습니다.
[Vue warn]: Error in watcher "people"
(found in anonymous component - use the "name" option for better debugging messages.)
그리고 내가 만든 코드 펜 에서 결과는 내가 예상했던 변경된 변경된 객체가 아니라 빈 배열입니다.
If anyone could suggest why this is happening or where I have gone wrong here then it would be greatly appreciated, many thanks!
Your comparison function between old value and new value is having some issue. It is better not to complicate things so much, as it will increase your debugging effort later. You should keep it simple.
The best way is to create a person-component and watch every person separately inside its own component, as shown below:
<person-component :person="person" v-for="person in people"></person-component>
Please find below a working example for watching inside person component. If you want to handle it on parent side, you may use $emit to send an event upwards, containing the id of modified person.
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>
I have changed the implementation of it to get your problem solved, I made an object to track the old changes and compare it with that. You can use it to solve your issue.
Here I created a method, in which the old value will be stored in a separate variable and, which then will be used in a watch.
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,
}
}
})
See the updated codepen
It is well defined behaviour. You cannot get the old value for a mutated object. That's because both the newVal and oldVal refer to the same object. Vue will not keep an old copy of an object that you mutated.
Had you replaced the object with another one, Vue would have provided you with correct references.
Read the Note section in the docs. (vm.$watch)
This is what I use to deep watch an object. My requirement was watching the child fields of the object.
new Vue({
el: "#myElement",
data:{
entity: {
properties: []
}
},
watch:{
'entity.properties': {
handler: function (after, before) {
// Changes detected.
},
deep: true
}
}
});
'Programing' 카테고리의 다른 글
| 오류 : __karma __. start 메소드를 구현하는 일부 어댑터를 포함해야합니다. (0) | 2020.09.22 |
|---|---|
| Symfony 2.8, 3.0 이상에서 buildForm ()에 데이터 전달 (0) | 2020.09.22 |
| .NET 목록 (0) | 2020.09.22 |
| 두 변수가 파이썬에서 동일한 객체를 참조하는지 비교 (0) | 2020.09.22 |
| WebView 리소스 요청에 사용자 지정 헤더 추가-Android (0) | 2020.09.22 |