It's easy in Vue to provide/give props or properties to a child element. Properties in Vue are one of the main ways we can pass data from a parent element or vue template to a child element. For example, in the code below, we give our child element PopularList
the property name
, and set it to Most Popular Posts
. That means that PopularList
can now access the data Most Popular Posts
:
<PopularList name="Most Popular Posts" />
However, sometimes child elements can contain other child elements. If we want to pass data from a parent component, to a grandchild component, an easier way of doing this is with provide/inject. This lets us provide data at a parent level, and inject it at any level below that.
This means if we have a property which is not used by the child, but is used by the grandchild, we don't have to unnecessarily pass it through both, like Parent → Child → GrandChild
- we can instead simply pass it as Parent → Grandchild
, as shown in the diagram below:
How to use provide and inject in Vue
If you are using the composition API, you can provide
any set of data using the provide
function:
<script setup>
import { provide } from 'vue'
provide('myKey', 'message');
</script>
provide
has both a key, and a value - above, the key is myKey
, and the value is message
. As with props, this could be an object, or a number, or any other valid type. We can also make this property reactive, so it stays up to date in the grandchild element by using the ref
function:
<script setup>
import { provide, ref } from 'vue'
const message = ref('message');
provide('myKey', message);
</script>
If you are using the Options API instead, you can provide data in a component using the following structure:
export default {
provide: {
myKey: 'message'
}
}
If you want the Options API version of reactivity in provide
, you have to use computed
. As such, the composition API is a little more straightforward to use with provide/inject
. We also need to use the provide()
notation if we are giving any per-instance state - i.e. where the data is coming from the data()
function.
export default {
data() {
return {
message: 'message'
}
},
provide() {
return {
// This sets `myKey` to the message property from data().
// Putting it in `computed()` makes it reactive.
myKey: computed(() => this.message)
}
}
}
Now that we've provided data, it can be accessed in any child component at any level by using the inject
function.
Accessing parent data using inject in Vue
Now that we've defiend provide
in a component, you can access that data using inject
. In a child component, or a grandchild component, we can access myKey
to refer to message
. For example, suppose we have a Vue component which looks like this:
<script setup>
import { ref, provide } from 'vue'
import ChildElement from './Child.vue';
const message = ref('message');
provide('myKey', message);
</script>
<template>
<p>Hello World!</p>
<ChildElement />
</template>
... And then a child element (Child.vue
) that looks like this:
<script setup>
import GrandChildElement from './GrandChildElement.vue';
</script>
<template>
<GrandChildElement />
</template>
Within GrandChildElement
, we can access myKey
, since we provided it in a parent. We could also do this in Child.vue
, but we could also just use props for that. provide
gives us the power to get data from multiple levels up. To access this data in GrandChildElement
, we use inject
. Our GrandChildElement.vue
file could look a little like this:
<script setup>
import { inject } from 'vue'
const message = inject('myKey')
</script>
const message
here will return the text message
, since that's what we set myKey
to with provide
. If you're using the Options API, you can do this instead:
export default {
inject: [ 'myKey' ],
created() {
// Can access this.myKey here
}
}
Now the value of myKey
is available to a grandchild component, without the need to pass it to the child first via props.
Top comments (2)
Yes, but I don't think that passing data to child components with this method is reactive.
It is if you use
computed
with the Options API as described above. It is reactive with compositions API by default