DEV Community

loading...
Cover image for How to Vue - Props vs Data

How to Vue - Props vs Data

proticm profile image Milos Protic ・4 min read

Vue is shipped with two ways of storing variables. One way is to use props, and the other way is to use data. Both of them can be defined on the Vue instance, as well as on the component.

At first, they might look confusing since they are very similar and seem to serve the similar purpose.

In this article, I will try to distinguish them and hopefully the difference will be more clear.

Props

Props are the way of how we can pass the data from a parent component down to any of its children.

When we build an application with Vue, we are doing it in a hierarchical way. What does this mean? It means that, starting from the Vue instance, the data flows from top to bottom and each data variable created on a parent can be passed down to its child via property.

The props can be defined as a an array of strings (names), but this will not cover the validations for the value passed to it. If validation is desired, an object needs to be listed with some specific configuration.

Also, good thing to point out is that we can pass a dynamic or static value to each of our properties.

Props as an array:

export default {
  name: 'my-component',
  props: ['name', 'surname']
}

Props as an object:

export default {
  name: 'my-component',
  props: {
    name: String, // must be a string
    surname: String, // must be a string
    propA: [String, Number], // allows multiple types
    propB: { // required string
      type: String,
      required: true
    },
    propC: {
      type: Number,
      default: 15 // the default value
    },
    propD: {
      validator: function (value) { // custom validator function
        return true
      }
    }
  }
}

If we run Vue in development mode, it will throw a warning each time when a prop type is invalid. In production mode this is not the case.

Ok, now when we know how to define the props, we should see how we can pass a value to it. This is done through the template.

Template:

<template>
  <div>
    Name: {{name}}
    Surname: {{surname}}
  </div>
</template>

We can pass a static value:

<my-component name="John" surname="Doe"></my-component>

or, if dynamic value is desired, we need to use v-bind directive:

<my-component v-bind:name="dynamicName" v-bind:surname="dynamicSurname"></my-component>

Note that camelCased properties need to use their kebab-cased equivalent. However, this limitation doesn't apply if a string template is used.

After all this being said, we should point out the importance of respecting one way data flow.

All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around.

This means that we don't need to worry about whether our child component property has the latest value from the parent. The props are reactive and this is all done for us. The Vue will make sure that each property has been updated after changing the parent value. If we try to update the child value by ourselves, the framework will throw a warning in the console.

Data

Data is the private memory of each component in your app where you can store any variables needed by it.

The data object is like the schema for your component’s state

In other words, we should use data config for the variables that are going to be used by the corresponding component only. If we need to pass this data to another component, we need to use props to pass it down to the children, or events to pass it up to the parent.

Our data should be configured as a function which returns an object where each property represents a variable which will be available within our template. By defining a data property as a function we are making sure that each instance of the component has its own copy of the data object.

<template>
    <span>{{message}}</span>
</template>
export default {
  name: 'my-component',
  data() {
    return {
      message: 'Hello!'
    }
  }
}

In the example above, if the message property wasn't defined as a data variable, the framework would throw a warning that we are trying to use something that does not exist.

Each variable defined within the data object will be reactive. This means that, like in the props example, we don't need to worry about value and template updating. This will be handled by the framework every time when the corresponding change occurs within our application.

Basically, as long as we are updating a reactive property (props, computed props, and anything in data), the framework will handle the updates for us.

Wrapping Up

Although props and data are similar, the difference at this point should be a little more clear and that they are meant to be used together in order to build a proper data flow within our application.

I would say that this line points out the key definition:

Both data and props are reactive, but data is more like "my own specific genes I've received when I was born" and props are "I expect to get these genes from my parent."

Thanks for reading and see you in the next article.

Discussion (13)

pic
Editor guide
Collapse
zymawy profile image
Ironside

Wow, Thank You For Such Explanations.
I Like The Way You Made The Differences For Both data, props.

Collapse
proticm profile image
Milos Protic Author • Edited

Thank you, I appreciate it.

Collapse
akwetey profile image
Jonathan Akwetey

is it possible to do a two way binding by using v-model to get dynamic props values?
I mostly do that for data.

Collapse
stikoo profile image
Alastair Hodgson

Yo Jonathan, v-modal is indeed used for two way binding, just not between parent-child components. You would use v-model to bind a components data to form inputs within the components

Collapse
proticm profile image
Milos Protic Author

If I understand the question correctly, I think that this should not be done in the first place.

Two way binding is exactly what its name says. A binding that goes in two directions. A property value comes from the parent data, so if you bind to it, since it is a two way binding, while changing the bound input value you are actually trying to mutate the parent data variable which, as said in this post is done with events ($emit option).

You are able to do this for data variables because, I assume, you have the data object defined on the component as a local state.

Collapse
akwetey profile image
Jonathan Akwetey

yeah you assumed correctly

Collapse
tarunvella profile image
tarunvella

An eye opener, Thanks a ton on explaining the subtle differences between data and props 🙌

Collapse
e_paul_ profile image
eli

Nice Publication ever, make me join the community so i can thank you

Collapse
proticm profile image
Milos Protic Author

No problem, glad it helped you

Collapse
marwicha profile image
marwicha • Edited

if you read the style guide of vue js is not recommended to define props type like this, it's better to do it like this for example:
props: {
propName: {
type: Object,
required: true,
},
propName: {
type: String,
required: true,
},
}

Collapse
mehdiraash profile image
Mehdi Raash

It has to be misleading, having two things but doing actually one thing, I like polymer project approach which data & prop are one, but you can specify it by a property.

Collapse
abidemit profile image
Tiamiyu Sikiru Abidemi

Thanks for the break down, it's an eye opener for me, learnt some vital lessons.

Collapse
proticm profile image
Milos Protic Author

No problem, glad I could help