in Vue.js, Vue.js Communication

Vue.js communication part 2: parent-child components

Many Vue.js app components will probably have some sort of parent-child relationship. In this part of the series I aim to talk about common patterns as well as anti-patterns that you should avoid.
If you follow the basic structure you should be safe for the future.
The goal is to understand how to write reusable components that are independent from the parent.

This is the second article of a series of Vue.js communication articles.

Outline

Rules

Those are the most important rules:

  • Parents are allowed to reference children, e.g. via props or refs
  • Children do not have any reference to the parent
  • Children do not change data that is passed via props.

Important: If the child is dependent on having a specific parent, then you cannot reuse the child component in other situations.

Anti-patterns

I’m going to start with some anti-patterns to set up the scene and make you aware of problems that might occur if you don’t follow the rules.

This will be obvious to many but I’m still going to demonstrate it.

This will work if the parent has a variable  username declared. But you couldn’t reuse it for other variables than  username .

There are other ways how to make the child dependent on the parent that are not that obvious anymore but can still lead to issues.

Here is a real life implementation that I have actually seen in a project. It seems like it’s decoupled, because it uses props and doesn’t reference $parent . But its implementation still makes assumptions about the environment it is being used in.

The real implementation was actually a lot more complex since it made a lot of decisions based on the  isHomepage flag.

This approach has a problem because the component is making assumptions about the parent that uses it.
It is better to think of features and let the parent configure its use case, e.g. the teaser component could have props like isTitleInset  or titleLocation  (‘inside’ or ‘outside’).
You might want to add additional features such as the title color or a set of hover animations. If you split these up into more props then you’ll gain more control for current and future use cases.

Always ask yourself:
Is this component independent from the parent?
Is it making assumptions about the parent?

Way down: Parent to child

Props

This is the most common way how to pass data down to a child. Just use a prop. There are different types of props you can pass, e.g. Number , String , Object , Function .

Numbers and strings are straight forward. Just pass them down.

There is a trap you can fall into, when passing down  Object . Make sure the child component doesn’t change properties on that object. It’s something I’ve seen in a real-life project as well.
Especially if you make it a habit to let the child change properties on an object you might end up not being able to understand where changes are coming from.

Don’t do this unless you have a really good reason:

Refs

In most cases you will use refs to reference DOM elements instead of vue components as we did on part 1 of this series.
There aren’t too many cases I can think of where I would want to use refs. But that might be taste.

I’ve seen a few vue components that provide public methods, e.g. for modals.

See on github: vue-admin’s modal implementation

To use the modal you would have to do this:

I personally would have tried to aim for props in that case. I wouldn’t add the extra complexity to provide methods and props for the same thing.

In this implementation there is a disconnect with visible  and show . When the modal sets show  to false , then the parent’s visible  variable might still be true .

Way up: Child to parent

There are two way how to pass data to the parent. Events and functions via props.
Events pass data up the tree.
Functions via props can be used for both passing data but also just to execute some work, such as painting on a canvas, start a file upload.

Events

Events are the standard way how to pass data up the tree. You can define events you like and pass any kind of data with it. The most common way how to listen to an event is to use v-on  or @  in your template when placing a child component. You can also use a ref like this

Note that there are two types of events. Native events and vue events. Depending on where you place the listener you might get a vue event object or a native one.

The main difference when planning your data flow is that vue events don’t bubble up the component tree. Every component in a nested tree needs to pass along the event by re-emitting it.

You’re going to receive a vue event when attaching a listener using v-on or @  to a child component that uses this.$emit to emit an event. If you still like to receive the native event then you need to add the native modifier like v-on:click.native or @click.native

This example demonstrates how to change from vue event to native events.

See the Pen Vue.js Native Events by Christian Gambardella (@gambo) on CodePen.0

Functions via props

You can pass functions via props if you want. These functions will be bound to the parent’s vue instance.
I personally don’t use this technique. I would rather use events. Just because the child component that should run a function will have to check if the function is present in order to prevent a run time error. But also because I don’t see a real benefit, yet. Would be great to see some good examples.

In certain cases it might make sense to use them though, e.g. if you’re building a paint application and have a toolbar of buttons.

See the Pen Vue.js: passing functions via props by Christian Gambardella (@gambo) on CodePen.0

Two way: v-model

In some cases parent and child component have to communicate two-way. That’s just as easy as combining what we’ve discussed before.

On the way down from the parent: change a child’s prop.
On the way up from the child: emits an event that the parent receives.

This is an example how to make it work for a text input component.

The child emits input events

The parent listens to the those events and sets the new value to firstName

The child receives back the new value using the prop

See the Pen yzBwYG by Christian Gambardella (@gambo) on CodePen.0

This is exactly what v-model  does. I’ve replaced the parent’s template with v-model

See the Pen Vue.js v-model by Christian Gambardella (@gambo) on CodePen.0

Final words

Parent child communication is going to be easy if you follow the rules.

When in doubt just use props and events.

Also have a look at the awesome guides to see detailed options and advanced options you have.

Further reading

  • Bob

    Another pattern is using the Flux architecture with Vuex. Although it doesn’t help make reusable components and everything becomes dependent on the central store.

    • Hey @disqus_UMXwbS1rlE:disqus that’s true!
      I’m going to cover that in the next post.
      This article is only about parents and children.