У меня есть массив, 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}
]
Обратите внимание, Фрэнку только что исполнилось 33 года.
У меня есть приложение, в котором я пытаюсь наблюдать за массивом людей, и при изменении любого из значений регистрирую это изменение:
<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.)
И в коде, который я сделал , результатом является пустой массив, а не измененный объект, который изменился, как я ожидал.
Если бы кто-нибудь мог предположить, почему это происходит или где я здесь ошибся, мы будем очень признательны, большое спасибо!
источник
Я изменил его реализацию, чтобы решить вашу проблему, я создал объект, чтобы отслеживать старые изменения и сравнивать их с этим. Вы можете использовать его для решения вашей проблемы.
Здесь я создал метод, в котором старое значение будет храниться в отдельной переменной и, которое затем будет использоваться в часах.
Смотрите обновленный код
источник
vm.$data
, спасибо!Это четко определенное поведение. Вы не можете получить старое значение для измененного объекта. Это потому, что и
newVal
иoldVal
относятся к одному и тому же объекту. Vue не будет хранить старую копию объекта, который вы изменили.Если бы вы заменили объект другим, Vue предоставил бы вам правильные ссылки.
Прочтите
Note
раздел в документации. (vm.$watch
)Подробнее об этом здесь и здесь .
источник
Это то, что я использую для более глубокого наблюдения за объектом. Моим требованием было наблюдение за дочерними полями объекта.
источник
Компонентное решение и решение с глубоким клонированием имеют свои преимущества, но также имеют проблемы:
Иногда вы хотите отслеживать изменения в абстрактных данных - не всегда имеет смысл создавать компоненты на основе этих данных.
Глубокое клонирование всей структуры данных каждый раз, когда вы вносите изменения, может оказаться очень дорогостоящим.
Думаю, есть способ получше. Если вы хотите просмотреть все элементы в списке и знать, какой элемент в списке был изменен, вы можете настроить специальные наблюдатели для каждого элемента отдельно, например:
С этой структурой
handleChange()
вы получите конкретный элемент списка, который изменился - оттуда вы можете выполнять любые действия, которые вам нравятся.Я также задокументировал здесь более сложный сценарий на случай, если вы добавляете / удаляете элементы в свой список (а не только манипулируете элементами, которые уже есть).
источник