7. Data Flow between Components in Vue.js
Just like any other application, the Components organization goes like a nested tree. For example, a simple website that includes a header, sidebar, and some other components in a container. The organization of the component would be like this.
Data Flow between Components
There can be two types of data flow between components:
- Parent component to Child Component
- Child component to Parent Component
We can send data from the parent component to the child component using props.
Child Component to Parent Component We can send data by emitting an event from the Child component and listen to it on the other end (Parent component).
Parent component to Child Component
As I mentioned that we can send data from the parent component to the child component using props.
Props are the way components can accept data from components that include them (parent components).
// hello.vue Component
<template>
<h1 class="title">Vue.js Component | {{msg}}</h1>
</template>
<script>
export default {
name: 'HelloComponent',
props: ['msg'],
data: ()=>({
}),
methods:{
}
}
</script>
<style>
.title{ color: red }
</style>
Accept multiple props
You can have multiple props by appending them to the array:
props: ['msg','fullName', 'age'],
Set the prop type
You can specify the type of a prop by using an object instead of an array, using the name of the property as the key of each property, and the type as the value:
props: {
firstName: String,
lastName: String
},
The valid types you can use are:
- String
- Number
- Boolean
- Array
- Object
- Date
- Function
- Symbol
When a type mismatches, Vue alerts (in development mode) in the console with a warning.
Prop types can be more articulated.
You can allow multiple different value types:
props: {
firstName: [String, Number],
lastName: String
},
Set a prop to be mandatory
You can require a prop to be mandatory:
props: {
firstName: {
type: String,
required: true
}
},
Set the default value of a prop
You can specify a default value:
props: {
firstName: {
type: String,
required: true,
default: 'Unknown person'
}
},
for object
props: {
name: {
type: Object,
default: {
firstName: 'Unknown',
lastName: ''
}
}
},
You can even build a custom validator, which is cool for complex data:
props: {
name: {
validator: name => {
return name === 'TechFerment' //only allow "TechFerment"
}
}
},
Passing props to the component
You pass a prop to a component using the syntax
<ComponentName color="white" />
if what you pass is a static value.
If it’s a data property, you use
<template>
<ComponentName :color="color" />
</template>
<script>
//... import component
export default {
//... register component
data: ()=>({
color: 'white'
}),
//...
}
</script>
You can use a ternary operator inside the prop value to check a truthy condition and pass a value that depends on it:
<template>
<ComponentName :color="color == 'white' ? true : false"/>
</template>
<script>
//... import component
export default {
//... register component
data: ()=>({
color: 'white'
}),
//...
}
</script>
Child component to Parent Component
Child Component to Parent Component We can send data by emitting an event from the Child component and listen to it on the other end (Parent component).
Here is the syntax for the child component for the emitting events.
// Without parameters(data)
this.$emit('eventName')// With Parameters(data)
this.$emit('eventName', param1, param2)
In this syntax, we need to be careful while giving a name to the event because using the same name; we will later listen to this event. In order to listen to this event, we can listen to it as we listen to a click event in Vue.js. For example
<myComponent @eventName="doSomething"></myComponent>
Example
// Child Component<script>
export default {
name: 'CarChildComponent',
methods: {
handleClick() {
this.$emit('clickedSomething')
}
}
}
</script>
The parent can intercept this using the v-on
directive when including the component in its template:
<template>
<div>
<Car v-on:clickedSomething="handleClickInParent" />
<!-- or -->
<Car @clickedSomething="handleClickInParent" />
</div>
</template>
<script>
export default {
name: 'App',
methods: {
handleClickInParent: function() {
//...
}
}
}
</script>
You can pass parameters of course:
// Child Component<script>
export default {
name: 'ChildComponent',
methods: {
handleClick() {
this.$emit('clickedSomething', param1, param2)
}
}
}
</script>
and retrieve them from the parent:
<template>
<div>
<Car v-on:clickedSomething="handleClickInParent" />
<!-- or -->
<Car @clickedSomething="handleClickInParent" />
</div>
</template>
<script>
export default {
name: 'App',
methods: {
handleClickInParent(params1, params2) {
//...
}
}
}
</script>
Keep watching this and follow us for more tech articles or you can reach out to me for any doubt and suggestions and the next blog in the series will be published soon.
Thanks
Happy Coding!