Estou tentando entender como observar corretamente algumas variações de objetos. Eu tenho um componente pai (arquivos .vue) que recebe dados de uma chamada ajax, coloca os dados dentro de um objeto e os usa para renderizar algum componente filho através de uma diretiva v-for, abaixo de uma simplificação da minha implementação:
<template>
<div>
<player v-for="(item, key, index) in players"
:item="item"
:index="index"
:key="key"">
</player>
</div>
</template>
... então <script>
tag interna :
data(){
return {
players: {}
},
created(){
let self = this;
this.$http.get('../serv/config/player.php').then((response) => {
let pls = response.body;
for (let p in pls) {
self.$set(self.players, p, pls[p]);
}
});
}
os objetos de item são assim:
item:{
prop: value,
someOtherProp: {
nestedProp: nestedValue,
myArray: [{type: "a", num: 1},{type: "b" num: 6} ...]
},
}
Agora, dentro do componente "player" do meu filho, estou tentando observar a variação de propriedade de qualquer item e uso:
...
watch:{
'item.someOtherProp'(newVal){
//to work with changes in "myArray"
},
'item.prop'(newVal){
//to work with changes in prop
}
}
Funciona, mas parece um pouco complicado para mim e eu queria saber se este é o caminho certo para fazê-lo. Meu objetivo é realizar alguma ação sempre que prop
mudar ou myArray
obter novos elementos ou alguma variação dentro dos existentes. Qualquer sugestão será apreciada.
fonte
"item.someOtherProp": function (newVal, oldVal){
como sugerido por Ron.keys
dentro de um objeto? Exemplo:"item.*": function(val){...}
Respostas:
Você pode usar um observador profundo para isso:
Agora, isso detectará quaisquer alterações nos objetos na
item
matriz e adições à própria matriz (quando usada com o Vue.set ). Aqui está um JSFiddle: http://jsfiddle.net/je2rw3rs/EDITAR
Se você não deseja assistir a todas as alterações no objeto de nível superior e apenas deseja uma sintaxe menos incômoda para assistir diretamente aos objetos aninhados, basta assistir a um
computed
:Aqui está o JSFiddle: http://jsfiddle.net/oa07r5fw/
fonte
computed
lugar: jsfiddle.net/c52nda7xwatch: { 'item.foo' : function(newVal, oldVal) { // do work here }}
bastante liso. Eu amo Vue!Outra boa abordagem e um pouco mais elegante é a seguinte:
(Aprendi essa abordagem com @peerbolte no comentário aqui )
fonte
ES5
sintaxe. Poderíamos, é claro, argumentar que oES2015 method definition
conteúdo em si não é muito elegante, mas meio que erra o objetivo da pergunta, que é como evitar colocar o nome entre aspas. Eu estou supondo que a maioria das pessoas estão encobrindo a pergunta original, que já contém a resposta, e estão realmente procurando por algo que, como você diz, não é muito bem documentado,Observação profunda do VueJs em objetos filho
fonte
Você pode usar o "observador dinâmico":
O
$watch
retorna uma função unwatch que irá parar de assistir se for chamado.Além disso, você pode usar a
deep
opção:Não deixe de dar uma olhada nos documentos
fonte
Note that you should not use an arrow function to define a watcher (e.g. searchQuery: newValue => this.updateAutocomplete(newValue)). The reason is arrow functions bind the parent context, so this will not be the Vue instance as you expect and this.updateAutocomplete will be undefined.
Não vendo isso mencionado aqui, mas também é possível usar o
vue-property-decorator
padrão se você estiver estendendo suaVue
classe.fonte
Outra maneira de acrescentar que eu costumava "hackear" essa solução era fazer isso: configurei um
computed
valor separado que simplesmente retornaria o valor do objeto aninhado.fonte
Meu problema com a resposta aceita do uso
deep: true
é que, ao observar profundamente uma matriz, não consigo identificar facilmente qual elemento da matriz contém a alteração. A única solução clara que encontrei é esta resposta, que explica como criar um componente para que você possa assistir cada elemento da matriz individualmente.fonte
oldVal
e osnewVal
dois fazem referência ao mesmo objeto, o mesmo acontece). A intenção de adeep watcher
é fazer algo quando os valores mudam, como emitir um evento, fazer uma chamada ajax etc. Caso contrário, você provavelmente deseja um componente, como apontado na resposta de Mani.Rastreando itens alterados individuais em uma lista
Se você deseja assistir a todos os itens de uma lista e saber qual item da lista foi alterado, é possível configurar observadores personalizados em cada item separadamente, da seguinte forma:
Se sua lista não for preenchida imediatamente (como na pergunta original), você poderá mover a lógica
created
para onde for necessário, por exemplo, dentro do.then()
bloco.Observando uma lista de alterações
Se a sua lista em si é atualizada para ter itens novos ou removidos, desenvolvi um padrão útil que "superficial" observa a própria lista e observa / desativa dinamicamente itens à medida que a lista muda:
fonte
Nenhuma das respostas para mim estava funcionando. Na verdade, se você deseja assistir a dados aninhados com componentes sendo chamados várias vezes. Então, eles são chamados com diferentes adereços para identificá-los. Por exemplo,
<MyComponent chart="chart1"/> <MyComponent chart="chart2"/>
Minha solução alternativa é criar uma variável de estado adicional vuex, que eu atualizo manualmente para apontar para a propriedade que foi atualizada pela última vez.Aqui está um exemplo de implementação do Vuex.ts:
Em qualquer função Component para atualizar a loja:
Agora em qualquer componente para obter a atualização:
fonte