Я пытаюсь понять, как правильно наблюдать за некоторым изменением опоры. У меня есть родительский компонент (файлы .vue), который получает данные от вызова ajax, помещает данные в объект и использует его для визуализации некоторого дочернего компонента с помощью директивы v-for, что ниже упрощения моей реализации:
<template>
<div>
<player v-for="(item, key, index) in players"
:item="item"
:index="index"
:key="key"">
</player>
</div>
</template>
... тогда внутри <script>
тега:
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]);
}
});
}
Объекты item выглядят так:
item:{
prop: value,
someOtherProp: {
nestedProp: nestedValue,
myArray: [{type: "a", num: 1},{type: "b" num: 6} ...]
},
}
Теперь внутри моего дочернего компонента "player" я пытаюсь следить за изменением свойств любого элемента и использую:
...
watch:{
'item.someOtherProp'(newVal){
//to work with changes in "myArray"
},
'item.prop'(newVal){
//to work with changes in prop
}
}
Это работает, но мне это кажется немного сложным, и мне было интересно, если это правильный способ сделать это. Моя цель - выполнять какие-то действия каждый раз, когда prop
меняется или myArray
получает новые элементы или некоторые изменения внутри существующих. Любое предложение будет оценено.
"item.someOtherProp": function (newVal, oldVal){
как предложено @Ron.keys
внутри объекта? Пример:"item.*": function(val){...}
Ответы:
Вы можете использовать глубокий наблюдатель для этого:
Теперь он будет обнаруживать любые изменения объектов в
item
массиве и дополнения к самому массиву (при использовании с Vue.set ). Вот JSFiddle: http://jsfiddle.net/je2rw3rs/РЕДАКТИРОВАТЬ
Если вы не хотите отслеживать каждое изменение в объекте верхнего уровня и просто хотите использовать менее неудобный синтаксис для непосредственного наблюдения за вложенными объектами, вы можете просто просмотреть
computed
вместо этого:Вот JSFiddle: http://jsfiddle.net/oa07r5fw/
источник
computed
вместо этого: jsfiddle.net/c52nda7xwatch: { 'item.foo' : function(newVal, oldVal) { // do work here }}
довольно гладко. Я люблю Vue!Еще один хороший и немного более элегантный подход заключается в следующем:
(Я узнал этот подход от @peerbolte в комментарии здесь )
источник
ES5
синтаксисе. Можно, конечно, утверждать, чтоES2015 method definition
само по себе это не очень элегантно, но оно как бы упускает из виду вопрос о том, как избежать переноса названия в кавычки. Я предполагаю, что большинство людей затушевывают оригинальный вопрос, который уже содержит ответ, и на самом деле ищут что-то, что, как вы говорите, не очень хорошо задокументировано,VueJs глубоко следит за дочерними объектами
источник
Вы можете использовать «динамический наблюдатель»:
$watch
Возвращает unwatch функцию , которая будет остановить смотреть , если она называется.Также вы можете использовать
deep
опцию:Пожалуйста, не забудьте взглянуть на документы
источник
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.
Не замечая этого, упомянутого здесь, но также возможно использовать
vue-property-decorator
шаблон, если вы расширяете свойVue
класс.источник
Еще один способ добавить, что я использовал для «взлома» этого решения, было сделать следующее: я установил отдельное
computed
значение, которое просто возвращало бы значение вложенного объекта.источник
Моя проблема с принятым ответом на использование
deep: true
заключается в том, что при глубоком просмотре массива я не могу легко определить, какой элемент массива содержит изменение. Единственное ясное решение, которое я нашел, - это ответ, который объясняет, как создать компонент, чтобы вы могли наблюдать за каждым элементом массива индивидуально.источник
oldVal
иnewVal
оба ссылаетесь на один и тот же объект, поэтому они одинаковы). Намерение adeep watcher
состоит в том, чтобы что-то сделать, когда значения изменяются, например, отправить событие, сделать ajax-вызов и т. Д. В противном случае вам, вероятно, понадобится компонент, как указано в ответе Мани.Отслеживание отдельных измененных элементов в списке
Если вы хотите просмотреть все элементы в списке и знать, какой элемент в списке изменился, вы можете настроить настраиваемые наблюдатели для каждого элемента отдельно, например, так:
Если ваш список заполнен не сразу (как в первоначальном вопросе), вы можете переместить логику
created
туда, где это необходимо, например, внутри.then()
блока.Просмотр меняющегося списка
Если ваш список обновляется, чтобы иметь новые или удаленные элементы, я разработал полезную схему, которая «поверхностно» наблюдает за самим списком и динамически отслеживает / отменяет просмотр элементов по мере изменения списка:
источник
Ни один из ответов для меня не работал. На самом деле, если вы хотите наблюдать за вложенными данными с компонентами, вызываемыми несколько раз. Поэтому их называют разными реквизитами, чтобы их идентифицировать. Например
<MyComponent chart="chart1"/> <MyComponent chart="chart2"/>
Мой обходной путь - создать дополнительную переменную состояния vuex, которую я вручную обновляю, чтобы указать свойство, которое было обновлено в последний раз.Вот пример реализации Vuex.ts:
На любой компонент функции для обновления магазина:
Теперь на любой компонент, чтобы получить обновление:
источник