SoFunction
Updated on 2025-04-05

A brief analysis of what is the use of provide / inject in vue

1. Preface

What does the parent-child component of vue use for communication?

: A combination of prop and $emit.

What if it is a grandfather component?

: Then you have to use the parent component to forward data and events.

What if it is the components of the great grandfather and grandson?

: Of course it's vuex

emmm OK, I'm fine, I'll leave now.

No, I can struggle for a while! There must be some brothers who are doing smaller projects, and there are not many components of communication, so they are too lazy to introduce vuex. Then provide/inject is the best solution to the communication problem of grandparents and grandchildren (not limited to grandparents and grandchildren, no matter how many levels are separated in the middle).

2. Introduction to copying official documents

This pair of options needs to be used together to allow an ancestor component to inject a dependency into all its descendants, regardless of the depth of the component hierarchy and always take effect during the time when the upstream and downstream relationship is established.

The provide option should be

  • An object or a function that returns an object. This object contains properties that can be injected into its descendants. In this object you can use ES2015 Symbols as key, but it only works in environments where Symbol and .

The inject option should be:

  • an array of strings, or
  • An object (click for detailsClick here )

3. Basic usage

// Ancestor component provides foo//The first typeexport default {
 name: "grandfather",
 provide(){
  return{
   foo:'halo'
  }
 },
}
//The second typeexport default {
 name: "grandfather",
 provide:{
  foo:'halo~~~~'
 },
}
//Destination component injects fooexport default {
 inject:['foo'],
}

Is there any difference between the above two usages?

  • If you just pass a string, like the 'halo' above, then there is no difference, and it can be read by descendants.
  • If you need to pass an object (code shown below), then the second type cannot be passed, and the descendant components cannot get the data. So it is recommended to write only the first one
//When you pass the object to descendantsprovide(){
  return{
   test:
  }
 },

Note: Once a certain data is injected, such as foo in the example above, the data foo cannot be declared in this component because it has been occupied by the parent.

4. When is it responsive?

If you have used vuex, then you will think that in the example above, if I change foo:'halo' to foo:'world', the child component will respond to data changes in a timely manner and the view will be updated.

Unfortunately, no

There is a saying in the official vue document

Tip: Provide and inject binding are not responsive. This is done deliberately. However, if you pass in an listenable object, then its object's properties are still responsive.

I won't discuss why vue is designed like this. I will only show when the provide/inject can respond.

provide(){
 return{
  test:
 }
},
data() {
 return {
  msg: "Welcome to Your  App",
 }
}
mounted(){
 setTimeout(()=>{
   = "halo world";
  (this._provided.msg)
  //log:Welcome to Your  App
 },3000)
},

As shown above, this is not possible. The data in the printed provided has not been changed, and the value obtained by the subcomponent has not changed.

You can even directly assign a value to this._provided.msg, but even if the value in _provided.msg changes, the value of the child component still remains unchanged.

When you do this like below, you can respond

provide(){
 return{
  test:
 }
},
data() {
 return {
  activeData:{name:'halo'},
 }
}
mounted(){
 setTimeout(()=>{
   = 'world';
 },3000)
}

This is the attributes of the object written in vue that can be responsive

However, if you pass in an listenable object, then its object's properties are still responsive.

5. Implement global variables

Global variables? Isn't provide/inject only passed from ancestors to descendants? That's right, we just need to bind to the top-level component.

It's you!

We throw an entire instance to the descendants!

//
export default {
 name: 'App',
 provide(){
  return{
   app:this
  }
 },
 data(){
  return{
   text:"it's hard to tell the night time from the day"
  }
 },
 methods:{
  say(){
   ("Desperado, why don't you come to your senses?")
  }
 }
}
//All other subcomponents require global variables, just need to inject the app as neededexport default {
 inject:['foo','app'],
 mounted(){
  ();//Get variables in the app  ();//You can execute methods in the app and transform them into global methods! }
}

This is responsive too

6. Implement page refresh

1. Use vue-router to rerout to the current page, and the page will not be refreshed.

2. When refreshing with () or (0), the entire browser is reloaded and flashes, and the experience is not good.

So how do we do it?

It's similar to the above principle. We only write a function in the component that controls the route (using v-if to control the display and hide of router-view, and the principle here is not detailed), and then pass this function to the descendant, and then call this method in the descendant component to refresh the route.

//
<router-view v-if="isShowRouter"/>
export default {
 name: 'App',
 provide(){
  return{
   reload:
  }
 },
 data(){
  return{
   isShowRouter:true,
  }
 },
 methods:{
  reload(){
    = false;
   this.$nextTick(()=>{
     = true;
   })
  }
 }
}
//Darks componentexport default {
 inject:['reload'], 
}

7. Ending

There is such a prompt in vue

Note: Provide and inject mainly provide use cases for advanced plug-ins/component libraries. It is not recommended to be used directly in application code.

Provide/inject is usually used less frequently, and most of them are used to develop components, but it is still very useful in some cases.

If the business is huge and complex, it is recommended to use vuex ~

Summarize

The above is what the use of provide / inject in vue introduced to you by the editor. I hope it will be helpful to everyone!