次のようなオブジェクトを含む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歳になったことに注意してください。
私は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>
私はこれを、配列比較についての 昨日私が尋ねた質問 に基づいており、最も早い回答を選びました。
だから、この時点で私は結果が表示されることを期待しています:{ 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 では、結果は空の配列であり、変更された変更されたオブジェクトではありません。
なぜこれが起こっているのか、ここで私が間違っていたのか誰かが示唆できたら、それは大いに感謝されるでしょう、どうもありがとう!
古い値と新しい値の比較機能に問題があります。後でデバッグ作業が増えるので、それほど複雑にしないことをお勧めします。あなたはそれを単純にしておくべきです。
以下のように、最良の方法はperson-component
を作成し、それ自身のコンポーネント内ですべての人を個別に監視することです。
<person-component :person="person" v-for="person in people"></person-component>
内部の人のコンポーネントを見るための実用的な例を以下に見つけてください。もしあなたが親の側でそれを処理したいのならば、あなたはid
を含むイベントを上向きに送るために$emit
を使うことができます。
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/[email protected]/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>
私はあなたの問題を解決するためにそれの実装を変更しました、私は古い変更を追跡しそれとそれを比較するためにオブジェクトを作りました。あなたはあなたの問題を解決するためにそれを使うことができます。
ここでは、古い値を別の変数に格納してウォッチで使用する方法を作成しました。
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,
}
}
})
更新されたcodepen を参照してください。
明確に定義された動作です。mutatedオブジェクトの古い値を取得することはできません。これは、newVal
とoldVal
の両方が同じオブジェクトを参照しているためです。 Vueはnot変更したオブジェクトの古いコピーを保存します。
オブジェクトを別のオブジェクトに置き換えた場合、Vueは正しい参照をあなたに提供していたでしょう。
これは私が物を深く見るために使うものです。私の要求はオブジェクトの子フィールドを監視することでした。
new Vue({
el: "#myElement",
data:{
entity: {
properties: []
}
},
watch:{
'entity.properties': {
handler: function (after, before) {
// Changes detected.
},
deep: true
}
}
});