How To Pass Data Between VueJS Components

Do you plan to move to the UK as a Global Talent?

Check this Out
Coding
Oct 1, 2021

One of VueJS' essential features is the ability to share data between components. It enables you to develop a more modular project, control data scopes, and maintain a natural data flow throughout your application.

Unless you build your entire Vue project in one component (which would be unrealistic), you'll have to share data between components. By the end of this tutorial, you'll learn how to use VueJS to share data between components.

1. Using Props To Share Data From Parent To Child Component

The simplest approach to share data between components is through VueJS props. Props are one-of-a-kind attributes that can be applied to a child component. Then, in our template, we can provide values to those properties, and voilà, we've passed data from a parent component to a child component!

Let's suppose we're working on an author's profile page and need a child component to accept a username prop. There are two things we'll need.

  1. The child component that accepts the prop; let’s call the component PostInfo.vue.

  2. The parent component that will pass the prop, let’s call the component AuthorsPage.vue.

Using the props option in Post.vue, we can indicate the props it accepts. 

 // PostInfo.vue  
 <template>  
  <div id='post-info'>  
   {{username}}  
  </div>  
 </template>  
 <script>  
 export default {  
  props: ['username']  
 }  
 </script>  

The data from the parent (AuthorsPage.vue) is then passed as a custom attribute to the child (PostInfo.vue).

 // AuthorsPage.vue  
 <post-info username='john-doe' /> 

Now, when we refresh the page, we can see that our PostInfo component renders the value supplied in by its parent (AuthorsPage.vue) correctly.

Additionally, we can use v-bind to dynamically pass properties just like we can with other VueJS directives. As an example, suppose we wish to set the username prop to a variable. We can achieve this by abbreviating the v-bind command (or just : for short). The code would be similar to this:

 <template>  
  <div>  
   <post-info :username="user.username" />  
  </div>  
 </template>  
 <script>  
 import PageInfo from "@/components/PageInfo.vue";  
 export default {  
  components: {  
   PageInfo  
  },  
  data() {  
   return {  
    user: {  
     username: 'john-doe'  
    }  
   }  
  }  
 }  
 </script>  

NB: Verify your props at all times:

To produce clear and clean Vue code, verifying your props is a crucial approach. In a nutshell, this means that you must specify the requirements for your prop (i.e. type, format, and so on). Vue will display a warning if one of these requirements is not met (for example, if the prop passed is an invalid type).

Let's suppose we only want Strings in our username prop, we will have to make the following changes to our props object:

 export default {  
  props: {  
   username: String  
  }  
 }  

In addition, when working on large-scale Vue projects or building plugins, verifying props is critical. It ensures that the props are used appropriately.

Also, I'd recommend reading through the official docs for a comprehensive list of the verifications we can place on props.

2. Emitting Events To Share Data From Child To Parent Component

Now that we have data flowing down the hierarchy, let's try it the other way around: from a child component to a parent component. We won't be able to use props, but we will be able to use custom events and listeners.

A .$emit(eventName) method can be called by any Vue instance to cause an event. Then, using the v-on directive, we can listen for this event.

Creating A Custom Event:
Let's continue on our author profile by adding a button that allows you to modify the username. Let's create the button in our child component (PostInfo.vue). When this button is clicked, we'll fire off a changeUsername event.

 //PostInfo.vue  
 <template>  
  <div id='post-info'>  
   <button @click='changeUsername()'>Change Username</button>  
   {{username}}  
  </div>  
 </template>  
 <script>  
 export default {  
  props: {  
   username: String  
  },  
  methods: {  
   changeUsername() {  
    this.$emit('changeUsername')  
   }  
  }  
 }  
 </script>  

We handle this event and modify the user.username variable inside the parent component. As discussed earlier, we can use the v-on directive, or "@" for short, to listen to events.

 <template>  
  <div>  
   <post-info :username="user.username" @changeUsername="user.username = 'new username'"/>  
  </div>  
 </template>  

Let's give it a shot. When you click the button, you should notice that the username changes to "new username."

NB: Custom Events Can Also Accept Arguments:

When you want a child component to be able to set a specific value for its prop, sending arguments to your events is the most common use case. Additionally, you should never modify a prop's value directly from the component.

Let's suppose we want to modify the changeUsername event to allow us to give a value to it.

The $emit method accepts an optional second parameter for arguments. So all we have to do now is append our new username value to the end of our event's name.

 this.$emit('changeUsername', 'new-john-doe')  

Then, in our parent component, we may use a custom $event variable to access these variables inline, or we can construct a handler method that accepts a parameter.

<page-info :username="user.username" @changeUsername="user.username = $event"/>  
 OR   
 <page-info :username="user.username" @changeUsername="changeUsername($event)"/>  
 export default {  
 ...  
 methods: {  
   changeUsername (username) {  
    this.user.username = username;  
   }  
 }  
 }  

Conclusion

To summarize, props can be used to share data from a parent component to a child component, whereas custom events can be used to share data from a child component to the parent component.

Finally, the official VueJS docs is a good place to go if you want to have a deep dive into props and custom events.









Author

James Olaogun
Hello, I'm
James E.

I'm a creative and analytical software engineer with a strong sense of teamwork. I also enjoy producing content to share my knowledge with other engineers and stakeholders.