Eu tenho uma matriz chamada people
que contém objetos da seguinte maneira:
Antes
[
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 32},
{id: 2, name: 'Joe', age: 38}
]
Pode mudar:
Depois de
[
{id: 0, name: 'Bob', age: 27},
{id: 1, name: 'Frank', age: 33},
{id: 2, name: 'Joe', age: 38}
]
Observe que Frank acabou de fazer 33 anos.
Tenho um aplicativo em que tento observar a matriz de pessoas e, quando qualquer um dos valores muda, registro a mudança:
<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>
Baseei isso na pergunta que fiz ontem sobre comparações de array e selecionei a resposta mais rápida.
Então, neste ponto, espero ver um resultado de: { id: 1, name: 'Frank', age: 33 }
Mas tudo o que recebo de volta no console é (tendo em mente que eu o tinha em um componente):
[Vue warn]: Error in watcher "people"
(found in anonymous component - use the "name" option for better debugging messages.)
E no codepen que fiz , o resultado é um array vazio e não o objeto alterado que mudou, o que seria o que eu esperava.
Se alguém pudesse sugerir por que isso está acontecendo ou onde eu errei aqui, ficaria muito grato, muito obrigado!
fonte
Eu mudei a implementação dele para ter seu problema resolvido, fiz um objeto para rastrear as mudanças antigas e compará-lo com isso. Você pode usá-lo para resolver seu problema.
Aqui criei um método, no qual o valor antigo será armazenado em uma variável separada e, que então será usado em um relógio.
Veja o codepen atualizado
fonte
vm.$data
, obrigado!É um comportamento bem definido. Você não pode obter o valor antigo de um objeto mutado . Isso porque ambos
newVal
e e seoldVal
referem ao mesmo objeto. O Vue não manterá uma cópia antiga de um objeto que você modificou.Se você tivesse substituído o objeto por outro, Vue teria fornecido as referências corretas.
Leia a
Note
seção nos documentos. (vm.$watch
)Mais sobre isso aqui e aqui .
fonte
É o que eu uso para observar profundamente um objeto. Minha exigência era observar os campos filho do objeto.
fonte
A solução de componente e a solução de clone profundo têm suas vantagens, mas também têm problemas:
Às vezes, você deseja rastrear alterações em dados abstratos - nem sempre faz sentido construir componentes em torno desses dados.
A clonagem profunda de toda a estrutura de dados sempre que você fizer uma alteração pode ser muito cara.
Acho que existe uma maneira melhor. Se você deseja observar todos os itens em uma lista e saber qual item da lista foi alterado, você pode configurar observadores personalizados em cada item separadamente, assim:
Com essa estrutura,
handleChange()
receberá o item específico da lista que mudou - a partir daí você poderá fazer o manuseio que desejar.Também documentei um cenário mais complexo aqui , no caso de você estar adicionando / removendo itens da sua lista (em vez de apenas manipular os itens já existentes).
fonte