DEV Community

Paul Wanjohi
Paul Wanjohi

Posted on

communication between components in Vue

we will use this sandbox to illustrate communication between different components, feel free to fork and play with it. I used tailwind for my styling. You'll need this when you have set a data property a component and you would like to render the data in another component or even mutate the data

parent to child communication

props allow one-way communication between a parent component and a child component. In the sandbox above, app.vue is our parent component with role as a data property, we want to pass the data from app component to ViewUser component, to do this we register a props property to ViewUser, this is an array with strings and in each string we specify properties which should be settable from outside, the name we set in our string has to match the name we use in our template.

ViewUser

To pass the prop we v-bind the prop name to the data property in the parent component where we render the template
<div class="flex"><ViewUser :role="role" /></div>

we can use props like a normal property, access it with this and run a method like seen in the example

  methods: {
    reverseRole() {
      return this.role
        .split('')
        .reverse()
        .join('');
    }
  }

To validate props we use the object syntax. If a requirement isn’t met, Vue will warn you in the browser’s JavaScript console at development time

  props: {
    role: String
  },

other validators to props are: Number, Boolean, Array, Object, Date, Function
and Symbol

child to parent

To demonstrate this we will make a button that will revert the role back to 'frontend developer' and pass the value from the child component- ViewUser.vue to the root component which is app.vue, for this we will use custom events. The child will emit a new event when data changes and the parent listens

when we initialize the vue instance we get the emit method, on emit we specify the name we want to emit and the data as the second argument as this.$emit('rolewasreset', this.mutatedrole);. we listen to the event emitted with the v-on directive or the shorthand @ in the selector of the component emitting the event inside the root component, the name must much the name we gave to emit event in our case the name was rolewasreset

customevents

passing the event
<ViewUser :role="role" @rolewasreset="role = $event;" />

note that we didn't mutate the prop directly but we defined a local data property that uses the prop as its initial value. if you do so you will get an warning in the console

sibling to sibling

For sibling to sibling communication, we will use eventBus. note that we can also use Vuex which we will not use in this example.

In our main.js, we create a new vue instance and store it in a constant which we export. we import in our edituser and viewuser where we emit the event and listen to the event respectively. eventBus is a vue instance, so we get the $emit method by default

edituser.vue

in a method inside our edituser component we call eventbus passing the required parameters eventBus.$emit('ageWasEdited', this.newAge);

viewuser.vue

we listen to the event in our viewuser component inside the create lifecycle hook using eventBus.$on('ageWasEdited', newAge => {
this.newAge = newAge;

the first parameter is the name of the event while the second is the data which is always a callback.

if we also render age in our root component you will notice once we edit the age the change won't reflect, meaning data is not passed to the parent then to the child receiving the data.

Hope this helped you understand how to communicate between components

Top comments (3)

Collapse
 
dimpadev profile image
Dimitri Pandeleakis

Note that the "sibling to sibling communication" you stated in the article is actually a global event bus which is a simple way of getting unrelated sections of your application to talk to each other. However, it is also considered an anti-pattern if not used correctly and it's really hard to maintain a medium-large codebase using exclusively this architecture. My recommendation would be: adopt vuex for everything as a default, and fall back to a global event bus if you think vuex becomes a substantial overhead in simple apps. I would only use a global event bus for events that don't necessarily mutate state or application data but only in rare cases/scenarios.
While it seems easier to set up and integrate a global event bus for "communicating between distant components", you will inevitably regret it once your app has achieved a certain size and level of complexity, especially once you need to refactor some of your views.

Collapse
 
paulwvnjohi profile image
Paul Wanjohi

thanks for highlighting that

Collapse
 
sotaan profile image
David Mamane

Don't forget to unbind the handler before destroying the component.
In your case:

beforeDestroy() {
eventBus.$off('ageWasEdited');
}

Also, you'd better refactor your handler in a method to unbind it specifically.