Tutorial

Vue.js Component Communication Patterns

Published on April 25, 2017
Default avatar

By Joshua Bemenderfer

Vue.js Component Communication Patterns

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

There are several methods that can be used for inter-component communication in Vue.js. Normal props and events should be sufficient for most cases, but there are other methods available at your disposal as well.

Props & Events

Of course, the normal method for communication involves props and events. This common pattern provides a powerful way of communicating between components without introducing any dependency or limitations on which components are involved.

Props:

Props allow you to pass any data type to a child component, and allow you to control what sort of data your component receives. Prop updates are also reactive, allowing a child component to update whenever parent data changes.

Template Usage:

<my-component v-bind:prop1="parentValue"></my-component>
<!-- Or more succinctly, -->
<my-component :prop1="parentValue"></my-component>

Events:

Events provide a way to inform your parent components of changes in children.

Template Usage:

<my-component v-on:myEvent="parentHandler"></my-component>
<!-- Or more succinctly, -->
<my-component @myEvent="parentHandler"></my-component>

Firing an Event:

...
export default {
  methods: {
    fireEvent() {
      this.$emit('myEvent', eventValueOne, eventValueTwo);
    }
  }
}

Additionally, you can create global event buses to pass events anywhere in your app. We’ve got an article on that.

Combined:

Using v-model allows for combining props with events for two-way binding. This is often used for input components. v-model assumes the value prop and input event, but this can be customized.

Template Usage:

<my-component v-model="prop1"></my-component>

A v-model compatible component:

<template>
  <div>
    <input type="text" :value="value" @input="triggerEvent"/>
  </div>
</template>

<script>
  export default {
    props: {
      value: String
    },

    methods: {
      triggerEvent(event) {
        this.$emit('input', event.target.value);
      }
    }
  }
</script>

Use When: You need to do pretty much any sort of data passing and messaging between components.

Provide / Inject

A much newer addition to Vue is the provide / inject mechanism. It allows for selective exposition of data or methods from an ancestor component to all of its descendants. While provide / inject is not itself reactive, it can be used to pass reactive objects.

provide / inject is probably not a good idea to develop an app with, but it can come in quite handy when writing whole custom-rendered component libraries.

Ancestor Component:

const SomethingAllDescendantsNeed = 'Air, probably.';

export default {
  provide: {
    SomethingAllDescendantsNeed
  }
}

Descendant Component(s):

export default {
  inject: ['SomethingAllDescendantsNeed'],

  mounted() {
    console.log(this.SomethingAllDescendantsNeed);
  }
}

Template Usage:

<ancestor-component>
  <div>
    <descendant-component>
      <p>
        <descendant-component></descendant-component>
      </p>
    </descendant-component>
  </div>
</ancestor-component>

(All descendant components, no matter how deep in the tree, have access to SomethingAllDescendantsNeed.)

Use When: Child components need access to an instance of something that’s only instantiated once per component tree. (Perhaps another library or an event bus.)

Direct Access

CAUTION: HERE BE SHARKS!

If you really, really, really, neeeeed to access a property or method directly on a parent or child component, you can use every component’s this.$parent and this.$children properties to have full access to everything on parent and children components. This is, however, and absolutely, horribly, despicably, terrible idea. If you find yourself in a situation where you need to do this, there’s a 99.99958% chance you did something wrong and should refactor.

Use When: DON’T. JUST DON’T.

Why not? Because you are introducing a direct coupling between both the implementation and structure in markup between parent and children components, making them inflexible and ridiculously easy to break.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Joshua Bemenderfer

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel