To pass data from parent to child components, we use props
in Vue. But as the application gets complex we may end up having deeply nested components. This means, passing props
in every component in the nested chain till the end component gets the data.
In Vue, we can use the provide
and inject
feature, which can help us avoid using the props
to pass data when dealing with deeply nested components.
The provide
option is used by the parent component to pass the data to the child component and using the inject
option, a child component can access this data.
In this article, we will look at how to declare and implement provide and inject options in Vue.js.
We will begin by creating a new application using Vue CLI.
vue create provide-inject-demo
Once, the installation is complete, we can navigate to the folder and run the server to load the application.
❯ cd provide-inject-demo
❯ npm run serve
This will run our server on port 8080 by default http://localhost:8080/
To demonstrate the provide and inject options, we will create two components:
- FirstComponent
- SecondComponent
We will import FirstComponent
in the App.vue
file and pass some data to the FirstComponent
. However, for demonstration purposes, the FirstComponent
will not make use of this data. Instead, SecondComponent
will be using it.
We will first make use of props
to implement it and later replace them with provide
and inject
options.
Let’s begin by editing the App.vue
.
// App.vue
<template>
<FirstComponent :msg="msg" />
</template>
<script>
import FirstComponent from "./components/FirstComponent.vue";
export default {
name: "App",
data() {
return {
msg: "Hello World!",
};
},
components: {
FirstComponent,
},
};
</script>
In this example, we are declaring a msg
property and passing it to FirstComponent
.
We haven’t created the FirstComponent.vue
file, so let’s create one. We will also go ahead and create another file called SecondComponent.vue
which we will be using later.
❯ touch src/components/FirstComponent.vue
❯ touch src/components/SecondComponent.vue
Let’s add some code in FirstComponent.vue
.
// FirstComponent.vue
<template>
<SecondComponent :msg="msg" />
</template>
<script>
import SecondComponent from "./SecondComponent.vue";
export default {
name: "FirstComponent",
props: ["msg"],
components: {
SecondComponent,
},
};
</script>
In this component, we are simply passing the msg
property to the SecondComponent
.
Next, we will add code to the SecondComponent.vue
file.
// SecondComponent.vue
<template>
<h2>Second Component - {{ msg }}</h2>
</template>
<script>
export default {
name: "SecondComponent",
props: ["msg"],
};
</script>
In this component, we are just displaying the message sent from the App
component.
As you can see, to be able to use the msg
property in the child component SecondComponent
, we had to pass the data via FirstComponent
. If we have deeply nested components, the msg
property will have to be passed via all the intermediate components in the hierarchy until the child component using the property receives it.
Let’s rewrite the above code using the project
and inject
options.
In the App.vue
we will create a provide
method that will include the msg
property that needs to be passed.
provide() {
return {
msg: this.msg,
};
}
The entire App.vue
file:
// App.vue
<template>
<FirstComponent />
</template>
<script>
import FirstComponent from "./components/FirstComponent.vue";
export default {
name: "App",
data() {
return {
msg: "Hello World!",
};
},
provide() {
return {
msg: this.msg,
};
},
components: {
FirstComponent,
},
};
</script>
Notice, we are not passing msg
property in <FirstComponent />
tag.
Now that the provide
option is available in the parent component App
we will modify both the child component files FirstComponent.vue
and SecondComponent.vue
.
// FirstComponent.vue
<template>
<SecondComponent />
</template>
<script>
import SecondComponent from "./SecondComponent.vue";
export default {
name: "FirstComponent",
components: {
SecondComponent,
},
};
</script>
Notice, we are no longer passing msg
prop in the FirstComponent.vue
file to the SecondComponent
.
Next, we will make changes in the SecondComponent.vue
file to include the inject
option.
inject: ["msg"];
The entire SecondComponent.vue
file:
<template>
<h2>Second Component - {{ msg }}</h2>
</template>
<script>
export default {
name: "SecondComponent",
inject: ["msg"],
};
</script>
This way we are able to make use of the msg
property in the child component SecondComponent
without having to pass props
.
Note: The provide
and inject
options are not a substitute for using props
and should be used only when it is necessary.