#vue.js #vue-component
#vue.js #vue-компонент
Вопрос:
Вот упрощенная версия моего кода:
Vue.component('entry', {
template: '
<div>
<label>Name: <input type="text" v-model="entry.name"></label>
</div>
',
props: ['entry']
});
Vue.component('entries', {
template: '
<div>
<entry v-for="entry in entries" :entry="entry"></entry>
<pre>{{ combined }}</pre>
</div>
',
props: ['entries'],
computed: {
combined: function() {
combined = [];
this.entries.forEach(function(entry) {
combined.push(entry.name);
});
return combined.join("n");
}
}
});
var entries = [
{name: "Entry 1"},
{name: "Entry 2"},
{name: "Entry 3"}
];
JSFiddle здесь:https://jsfiddle.net/msw3Lx98/3 /
Компонент верхнего уровня ( entries
) принимает список объектов и создает подкомпонент ( entry
) для каждого из них. Подкомпонент привязывает входные данные к входным.
Когда пользователь изменяет данные, вводя их в один из входных данных, компоненту верхнего уровня необходимо перенести обновленное значение combined
в отдельный бит кода.
Мое понимание модели наблюдателя заключается в том, что если компонент верхнего уровня наблюдает, entries
он может обнаруживать, когда что-то добавляется в список или удаляется из него, но не когда данные внутри записи меняются.
Однако компонент верхнего уровня явно каким-то образом видит такого рода изменения, потому что при вводе пользователем входных данных значение combined
обновляется.
Существует ли «правильный» способ обнаружения такого рода изменений?
Вот несколько вариантов, которые я исследовал:
- Определите
updated
метод для подкомпонента. В этом методе генерируется пользовательское событие и обрабатывается это событие в родительском. Это довольно неудобно, и я не думаю, что это будет хорошо масштабироваться. - Определите
beforeUpdate
метод для родительского элемента — это (но неupdated
) выполняется всякий раз, когда происходит изменение в подкомпоненте. Я не уверен, почему, и мне это не нравится. - В компоненте верхнего уровня следите за
combined
свойством. Я немного удивлен, что это работает, но это так. Это кажется наиболее простым вариантом, но из документов Vue не очевидно, что вычисляемые свойства предназначены для просмотра, поэтому я неохотно полагаюсь на это.
Ответ №1:
Одним из преимуществ VueJS является то, что он позволяет разработчикам нормально кодировать с учетом бизнес-логики, в то время как фреймворк заботится о производительности, используя свою систему реактивности.
VueJS делает это, определяя методы получения и установки для известных объектов и массивов при создании экземпляра компонента.
Вот обновленная скрипка (разветвленная из вашей версии):https://jsfiddle.net/6wkyfxs6/3 /
Как вы можете видеть, я добавил метод в addNewEntry
, который позволяет добавить «Элемент 4» в список.
Неудивительно, что первые 3 элемента имеют методы наблюдателя, поскольку они были созданы при создании экземпляра Vue. Но если вы добавите «Элемент 4» в мою новую скрипку, которого изначально не было, даже он будет замечен, и изменения будут уведомлены. Так работает система реактивности.
При более глубокой проверке, если вы установите window.entries = this.entries
внутри компонента entries и проверите в консоли, вы заметите, что у него есть метод observer ( entries.__ob__
) на верхнем уровне. Вот скриншот (взятый из локальной версии в Google Chrome, а не на jsFiddle):
Это то, что Vue использует для обновления и уведомления себя об изменениях в массиве в целом, в отличие от Angular 1.x, который использует грязную проверку. Таким образом, каждый раз, когда вы что-то меняете внутри Vue, система реактивности запускает и настраивает наблюдателей (вместе с получателями / установщиками) для всех новых и измененных объектов.
Система реактивности не сработает, если вы добавите или измените объект непосредственно в javascript. В частности, в случае массивов (как в вашем примере), есть некоторые предостережения, как показано здесь:https://vuejs.org/guide/list.html#Caveats , но в вашем примере отсутствуют эти оговорки.
Таким образом, VueJS позволяет разработчикам вроде нас нормально кодировать с учетом бизнес-логики, одновременно заботясь об оптимизации производительности. Я не думаю, что вам следует использовать какой-либо из методов updated
или beforeUpdate
, если вы не столкнетесь с некоторыми проблемами — в этом случае первым выбором должно быть сообщение об ошибке вместо обходных путей.
Комментарии:
1. Это просто повторяет то, что есть в документах Vue, что не отвечает на вопрос. Я знаю, что данные изменились, и Vue тоже это знает. Вопрос в том, где я могу правильно подключить свою собственную функциональность, которая будет вызвана этим изменением.
2.
watch
это правильное место для подключения вашей функциональности к изменениям объекта, какentry
в вашем примере. Но если вы попытаетесь посмотретьentries
, это не сработает, если вы не добавляете новые записи. Запускается только вычисляемое свойство —combined
-, поскольку оно зависит от отдельныхentry
объектов.