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.
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 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 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.
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.)
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.
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.
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!