vue 3 learning notes -- Usage and principle of provide and inject

Keywords: Vue

props and emit are usually used when transmitting data between parent and child components. props is used when transmitting data from parent to child. If a parent component transmits data to a child component, it needs to be transmitted to the child component first, and then to the child component. If multiple child components or multiple child components are used, it needs to be transmitted many times, which will be very troublesome.

In this case, you can use provide and inject to solve this problem. No matter how deep the component is nested, the parent component can provide data for all child components or grandchildren. The parent component uses provide to provide data, and the child components or grandchildren inject data. At the same time, it is more convenient to transfer values between brother components.

1, Vue2's provide / inject usage

provide: an object containing attributes and values. For example:

provide:{
 info:"value"
}

 

If provide needs to use the data in data, an error will be reported. When accessing the component instance property, you need to convert provide into a function that returns an object.

provide(){
 return{
  info: this.msg
 }
}

 

inject: is an array of strings. For example:

inject: [ 'info' ]

 

Receive the info data provided by the above provider, or it can be an object. The object contains the from and default attributes. From is the key used for searching in the injected content, and the default attribute specifies the default value.

In vue2, project / inject applies:

//Parent component
export default{
 provide:{
  info:"Provide data"
 }
}
//Subcomponents
export default{
 inject:['info'],
 mounted(){
     console.log("Receive data:", this.info) // Receiving data: providing data
 }
} 

 

provide / inject is similar to the subscription and publication of messages. provide provides or sends data, and inject receives data.

2, Vue3's provide / inject usage

provide/inject is used in the composite API. The two can only be called during setup. Before use, the provide/inject method must be imported from vue display.

The provide function receives two parameters:

provide( name,value )

Name: defines the name of the property provided.

Value: the value of property.

When in use:

import { provide } from "vue"
export default {
  setup(){
    provide('info',"value")
  }
}

 

The inject function has two parameters:

inject(name,default)

Name: receive the attribute name provided by the provider.

Default: set the default value. It can be left blank. It is an optional parameter.

When in use:

import { inject } from "vue"
export default {
  setup(){
    inject('info',"Set defaults")
  }
}

 

Complete instance 1: provide/inject instance

//Parent component code
<script>
import { provide } from "vue"
export default {
  setup(){
    provide('info',"value")
  }
}
</script>

//Sub component code
<template>
 {{info}}
</template>
<script>
import { inject } from "vue"
export default {
  setup(){
    const info = inject('info')
    return{
      info
    }
  }
}
</script>

 

3, Add responsiveness

To add responsiveness to provide/inject, use ref or reactive.

Complete example 2: provide/inject response

//Parent component code
<template>
  <div>
    info: {{info}}
    <InjectCom ></InjectCom>
  </div>
</template>
<script>
import InjectCom from "./InjectCom"
import { provide,readonly,ref } from "vue"
export default {
  setup(){
    let info = ref("Did you study today?")
    setTimeout(()=>{
      info.value = "Learn without excuses"
    },2000)
    provide('info',info)
    return{
      info
    }
  },
  components:{
    InjectCom
  }
}
</script>

// InjectCom Sub component code
<template>
 {{info}}
</template>
<script>
import { inject } from "vue"
export default {
  setup(){
    const info = inject('info')
    setTimeout(()=>{
      info.value = "to update"
    },2000)
    return{
      info
    }
  }
}
</script>

 

In the above example, the value of info will be modified in both parent and child components.

provide / inject is similar to the subscription and publication of messages. It follows the single data flow in vue. What does it mean? Where the data is, the modification can only be made, and the data cannot be modified at the data transfer, which is easy to cause unpredictable status.

When modifying the value in the subscription component, it can be modified normally. If other components also use the value, the state is easy to cause confusion, so it is necessary to avoid the problem at the source.

readonly   Read only functions need to be introduced before use. If the readonly attribute is added to a variable, the data can only be read and cannot be changed. A warning will be issued when it is modified, but the value will not be changed.

usage method:

import { readonly } from "vue"
let info = readonly('read-only info value')
setTimout(()=>{
 info="to update info" //Update in two seconds info Value of
},2000)

 

After running for two seconds, the browser issues a warning that the info value cannot be modified.

Therefore, we add a read-only attribute to the data transmitted by provide to prevent the transmitted data from being modified.

Add readonly at the provide of complete instance 2.

provide('info', readonly(info))

 

When the sub component modifies the value, there will be a read-only reminder.

When modifying the value, you still need to modify the data in the component that provide s the data, so you will add the modification method in the component and publish it at the same time. You can call it at the sub component. For example:

//release
let info = ref("Did you study today?")
const changeInfo = (val)=>{
 info.value = val
}
provide('info',readonly(info))
provide('changeInfo',changeInfo)

//subscribe
const chang = inject('changeInfo')
chang('Rush to the front end Engineer')

 

Complete example 3: modifying data

// Parent component code
<template>
  <div>
    info: {{info}}
    <InjectCom ></InjectCom>
  </div>
</template>

<script>
import InjectCom from "./InjectCom"
import { provide,readonly,ref } from "vue"
export default {
  setup(){
    let info = ref("Did you study today?")
    const changeInfo = (val)=>{
      info.value = val
    }
    provide('info',readonly(info))
    provide('changeInfo',changeInfo)
    return{
      info
    }
  },
  components:{
    InjectCom
  }
}
</script>

//InjectCom Sub component code
<template>
  <div>
    <button @click="chang('Rush to the front end Engineer')">Update value</button>
  </div>
</template>
<script>
import { inject } from "vue"
export default {
  setup(){
    const info = inject('info')
    const chang = inject('changeInfo')
    return{
      info,
      chang
    }
  }
}
</script>

 

Posted by sklein99 on Thu, 25 Nov 2021 20:09:07 -0800