Mam tablicę o nazwie, people
która zawiera następujące obiekty:
Przed
[
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 32},
{id: 2, name: 'Joe', age: 38}
]
Może się zmienić:
Po
[
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 33},
{id: 2, name: 'Joe', age: 38}
]
Zauważ, że Frank właśnie skończył 33 lata.
Mam aplikację, w której próbuję obserwować tablicę osób i gdy dowolna z wartości zmienia się, rejestruję zmianę:
<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>
Oparłem się na pytaniu, które zadałem wczoraj na temat porównań tablic i wybrałem najszybszą działającą odpowiedź.
Tak więc w tym miejscu spodziewam się wyniku: { id: 1, name: 'Frank', age: 33 }
Ale wszystko, co otrzymuję w konsoli, to (pamiętając, że miałem ją w komponencie):
[Vue warn]: Error in watcher "people"
(found in anonymous component - use the "name" option for better debugging messages.)
A w kodowaniu, które stworzyłem , wynikiem jest pusta tablica, a nie zmieniony obiekt, który się zmienił, czego się spodziewałem.
Gdyby ktoś mógł zasugerować, dlaczego tak się dzieje lub gdzie popełniłem błąd, byłoby to bardzo wdzięczne, wielkie dzięki!
źródło
Zmieniłem implementację, aby rozwiązać twój problem, zrobiłem obiekt, aby śledzić stare zmiany i porównać go z tym. Możesz go użyć do rozwiązania problemu.
Tutaj stworzyłem metodę, w której stara wartość będzie przechowywana w osobnej zmiennej i która następnie zostanie wykorzystana w zegarku.
Zobacz zaktualizowany kodeks
źródło
vm.$data
, dziękuję!Jest to dobrze zdefiniowane zachowanie. Nie można uzyskać starej wartości dla zmutowanego obiektu. Dzieje się tak, ponieważ zarówno atrybuty, jak
newVal
ioldVal
odnoszą się do tego samego obiektu. Vue nie zachowa starej kopii obiektu, który zmutowałeś.Gdybyś wymienił obiekt na inny, Vue dostarczyłby ci poprawnych referencji.
Przeczytaj
Note
sekcję w dokumentacji. (vm.$watch
)Więcej na ten temat tutaj i tutaj .
źródło
To jest to, czego używam do głębokiego oglądania obiektu. Moim wymaganiem było obserwowanie pól potomnych obiektu.
źródło
Rozwiązanie komponentu i rozwiązanie głębokiego klonu mają swoje zalety, ale mają również problemy:
Czasami chcesz śledzić zmiany w abstrakcyjnych danych - nie zawsze ma sens budowanie komponentów wokół tych danych.
Głębokie klonowanie całej struktury danych za każdym razem, gdy wprowadzasz zmianę, może być bardzo kosztowne.
Myślę, że jest lepszy sposób. Jeśli chcesz obserwować wszystkie elementy na liście i wiedzieć, który element na liście się zmienił, możesz skonfigurować niestandardowe obserwatory dla każdego elementu osobno, na przykład:
Dzięki tej strukturze
handleChange()
otrzymasz określoną pozycję listy, która uległa zmianie - stamtąd możesz wykonać dowolną obsługę.Udokumentowałem tutaj również bardziej złożony scenariusz , na wypadek, gdybyś dodawał / usuwał elementy do swojej listy (zamiast tylko manipulować przedmiotami już tam istniejącymi).
źródło