$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.
ChildA now has a
GrandchildA component that gets an
input event bound onto its tag, and it passes the
desserts data it receives from
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.
GrandchildA will pass its data to
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
this.$emit('input', this.desserts), and
ChildA does the same and passes the data to
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 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
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.
Now let's modify
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
this.$parent to execute the callback function in
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:
desserts data is updated from
GrandchildA directly to
Parent, then passed down to
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
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:
$children is an array of VueComponent instances and there is only one child for both
ChildA, we can use
Now if the user clicks the button:
An alert is shown as expected.
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:
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: