$parent and $children patterns
In Part 1 of this series, we introduced two patterns that work perfectly in a two-level component hierarchy, but what about a three-level or even four or five-level hierarchy?
Now following the starting examples of Part 1,
let's add a new component GrandchildA
, and here is the initial state of the three components:
Parent
has a ChildA
component that gets an input
event bound onto its tag. This is the "custom v-model" pattern discussed in Part 1.
Similar to Parent
, ChildA
now has a GrandchildA
component that gets an input
event bound onto its tag, and it passes the desserts
data it receives from Parent
into GrandchildA
. Notice the watch function for its prop value
at line 38, this is to make sure whenever the prop changes, ChildA.desserts
will get the latest value.
Also, GrandchildA
will pass its data to ChildA
, and ChildA
will pass it back to Parent
, as seen in lines 43 - 46.
GrandchildA
has the same settings as ChildA
in Part 1, it has a button where we can add a new dessert.
In the event handler function handleUpdate
, it will use $emit
to trigger the input
event bound onto it in ChildA
, and pass the new data as the argument.
Here is the current view:
Now if the user clicks the Update
button on GrandchildA
, the view becomes:
GrandchildA
sends the updated desserts
to ChildA
by this.$emit('input', this.desserts)
, and ChildA
does the same and passes the data to Parent
, Parent
updates its this.desserts
using the new value, and passes it down to ChildA
as a prop. ChildA
is watching the prop value change, so it will update its this.desserts
, and this.desserts
is passed down to GrandchildA
as a prop.
So in order for GrandchildA
to communicate with Parent
, it must go through the middle man ChildA
. How about now we add a GrandGrandchild
component? It will follow the same approach, and both ChildA
and GrandchildA
will become the middle man. When it comes to a multi-level hierarchy, we can repeat the two patterns from Part 1 in each descendant component, but there is a better way.
$parent pattern
Now let's modify GrandchildA.handleUpdate()
:
Thanks to the exquisite design of Vue, we don't really need to trigger the input
event on GrandchildA
and then execute the callback function in ChildA
. Instead, in GrandchildA
we can directly trigger the input
event on ChildA
using this.$parent
to execute the callback function in Parent
, because GrandchildA.$parent
= ChildA
. Super simple, isn't it?
Since we don't need ChildA
to do the middle man work anymore, now ChildA
can be very simple:
ChildA
becomes to only receive a prop and pass it to GrandchildA
. If we click the Update
button now, it works the same:
The new desserts
data is updated from GrandchildA
directly to Parent
, then passed down to ChildA
and GrandchildA
.
$children pattern
In a Vue component tree, there is $parent
, and of course, there is $children
as well. Let's see an example of $children
. We will leave GrandchildA
as is, while in ChildA
, now we bind a new event named show:alert
onto the GrandchildA
tag:
And the event callback function is handleShowAlert
which will show an alert. Now in Parent
, let's add a new button:
When clicking the button, we want to trigger the show:alert
event on GrandchildA
, which will, in turn, execute ChildA.handleShowAlert()
to show the alert. This is achieved using:
this.$children[0].$children[0].$emit('show:alert');
Because $children
is an array of VueComponent instances and there is only one child for both Parent
and ChildA
, we can use $children[0]
.
Now if the user clicks the button:
An alert is shown as expected.
Conclusion
For a multi-level hierarchy of components, the "$parent and $children" patterns are suitable as they can reduce the level-by-level data passing between components. But if there are too many levels, then we would have to do something like this:
this.$parent.$parent.$parent.$parent.$emit('input', this.desserts);
Also, a parent component can have many children components, and each child component can have its many children components. How can we pinpoint a specific child component in the $children
array? This question will lead us to Part 3 of this series where we will look to solve it.
Here are all the articles in this series:
Vue.js Components Communication Patterns (without Vuex) - Part 1
Vue.js Components Communication Patterns (without Vuex) - Part 2
Vue.js Components Communication Patterns (without Vuex) - Part 3
Vue.js Components Communication Patterns (without Vuex) - Part 4
Vue.js Components Communication Patterns (without Vuex) - Part 5
Vue.js Components Communication Patterns (without Vuex) - Part 6
Vue.js Components Communication Patterns (without Vuex) - Part 7
Top comments (0)