Шаблоны $parent и $children
В Части 1 этой серии мы представили два шаблона, которые отлично работают в двухуровневой иерархии компонентов, но как насчет трехуровневой, или даже четырех-, или пятиуровневой иерархии? Теперь, следуя начальным примерам Части 1, добавим новый компонент GrandchildA
, и вот начальное состояние трех компонентов:
Parent
имеет компонент ChildA
, который получает событие input
, привязанное к его тегу. Это паттерн пользовательская v-модель, обсуждавшийся в Части 1.
Подобно Parent
, ChildA
теперь имеет компонент GrandchildA
, который получает событие input
, привязанное к его тегу, и передает данные desserts
, полученные от Parent
, в GrandchildA
. Обратите внимание на функцию наблюдения за реквизитом value
в строке 38, это делается для того, чтобы каждый раз при изменении реквизита ChildA.desserts
получало самое последнее значение.
Кроме того, GrandchildA
передаст свои данные ChildA
, а ChildA
передаст их обратно Parent
, как показано в строках 43–46.
GrandchildA
имеет те же настройки, что и ChildA
в Части 1, у него есть кнопка, куда мы можем добавить новый десерт. В функции обработчика событий handleUpdate
он будет использовать $emit
для запуска события input
, связанного с ним в ChildA
, и передавать новые данные в качестве аргумента.
Вот текущий вид:
Теперь, если пользователь нажмет кнопку Update
на GrandchildA
, представление станет таким:
GrandchildA
отправляет обновленный desserts
ChildA
с помощью this.$emit('input', this.desserts)
, а ChildA
делает то же самое и передает данные Parent
, Parent
обновляет свой this.desserts
, используя новое значение, и передает его ChildA
в качестве опоры. ChildA
наблюдает за изменением значения реквизита, поэтому он обновит свой this.desserts
, а this.desserts
будет передан GrandchildA
в качестве реквизита.
Таким образом, чтобы GrandchildA
мог общаться с Parent
, он должен пройти через посредника ChildA
. Как насчет добавления компонента GrandGrandchild
? Он будет следовать тому же подходу, и ChildA
и GrandchildA
станут посредниками. Когда дело доходит до многоуровневой иерархии, мы можем повторить два шаблона из Части 1 в каждом компоненте-потомке, но есть способ получше.
$родительский шаблон
Теперь давайте изменим GrandchildA.handleUpdate()
:
Благодаря изысканному дизайну Vue нам на самом деле не нужно запускать событие input
в GrandchildA
, а затем выполнять функцию обратного вызова в ChildA
. Вместо этого в GrandchildA
мы можем напрямую инициировать событие input
в ChildA
, используя this.$parent
для выполнения функции обратного вызова в Parent
, потому что GrandchildA.$parent
= ChildA
. Супер просто, не так ли?
Поскольку нам больше не нужен ChildA
для выполнения работы посредника, теперь ChildA
может быть очень простым:
ChildA
становится только получать реквизит и передавать его GrandchildA
. Если мы сейчас нажмем кнопку Update
, она будет работать так же:
Новые данные desserts
обновляются из GrandchildA
непосредственно в Parent
, а затем передаются в ChildA
и GrandchildA
.
$детский шаблон
В дереве компонентов Vue есть $parent
и, конечно же, $children
. Давайте посмотрим на пример $children
. GrandchildA
оставим как есть, а в ChildA
теперь привязываем новое событие с именем show:alert
на тег GrandchildA
:
И функция обратного вызова события — handleShowAlert
, которая покажет предупреждение. Теперь в Parent
добавим новую кнопку:
При нажатии кнопки мы хотим инициировать событие show:alert
для GrandchildA
, которое, в свою очередь, выполнит ChildA.handleShowAlert()
для отображения предупреждения. Это достигается с помощью:
this.$children[0].$children[0].$emit('show:alert');
Поскольку $children
— это массив экземпляров VueComponent и для Parent
и ChildA
есть только один дочерний элемент, мы можем использовать $children[0]
. Теперь, если пользователь нажмет кнопку:
Предупреждение отображается, как и ожидалось.
Заключение
Для многоуровневой иерархии компонентов подходят шаблоны «$parent и $children», поскольку они могут уменьшить поуровневую передачу данных между компонентами. Но если уровней слишком много, то нам придется сделать что-то вроде этого:
this.$parent.$parent.$parent.$parent.$emit('input', this.desserts);
Кроме того, у родительского компонента может быть много дочерних компонентов, а у каждого дочернего компонента может быть множество дочерних компонентов. Как определить конкретный дочерний компонент в массиве $children
? Этот вопрос приведет нас к части 3 этой серии, где мы постараемся его решить.
Вот все статьи из этой серии:
Шаблоны взаимодействия компонентов Vue.js (без Vuex) — часть 1
Шаблоны взаимодействия компонентов Vue.js (без Vuex) — часть 2
Шаблоны взаимодействия компонентов Vue.js (без Vuex) — часть 3
Шаблоны взаимодействия компонентов Vue.js (без Vuex) — часть 4
Шаблоны взаимодействия компонентов Vue.js (без Vuex) — часть 5
Шаблоны взаимодействия компонентов Vue.js (без Vuex) — часть 6
Шаблоны взаимодействия компонентов Vue.js (без Vuex) — часть 7