Vue 爷孙组件通讯之:Provide / Inject 详细介绍

背景

       在父子组件传递数据时,通常使用的是 props 和 emit,父传子时,使用的是 props,如果是父组件传孙组件时,层层传递非常麻烦。

        对于这种情况,我们可以使用一对 provide 和 inject。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。

        这个特性有两个部分:父组件有一个 provide 选项来提供数据,子组件有一个 inject 选项来开始使用这些数据。

vue2中的使用:

使用1: A->C 传递数据;

假设有一个组件A,A组件引入B组件(A为B的父组件) ,B组件引入C组件(B为C的父组件),即A为C的祖先组件,此时二者可以使用provide / inject进行通信。

-------------------------------- A 组件 ---------------------
<template>
  <div>
    <B></B>
  </div>
</template>
 
<script>
import B from "./B.vue";
export default {
  name: "A",
  components: {
    B
  },
  provide:{
    name:"我是A提供的数据name",    // 这种情况下,非响应式,可以写成return的形式作为响应式
  },
    provide:{
        return {
            obj:this.obj,
            age:12,
        }
    }
   
};
</script>
------------------------------ B 组件 ---------------------------
<template>
  <div>
    <C></C>
  </div>
</template>
 
<script>
import C from "./C.vue";
export default {
  name: "B",
  components: {
    C
  },
};
</script>
-------------------------------C组件-------------------------------------
<template>
  <div>
        {{name}}          // 非响应式写法
        {{obj.name}}      // 响应式
        {{age}}
  </div>
</template>
 
<script>
export default {
  name: "C",

  inject:["name","obj","age"]        // C组件在这里使用inject继承和接受a的数据
};
</script>

此时A中的name改变,C中的值也会相应跟着变化。

使用2: C->A  改变数据;

        以上为A向C传数据,如果C向A传数据(或者说C需要改变A中的数据),该如何做?

我们这里不让C直接改变A中的数据,而是将A改变数据的方法通过provide传给C,C执行该方法,触发改变A中的数据。

A使用provide传入一个方法

<template>
  <div>
    <span>{{obj.name}}</span>
    <B></B>
  </div>
</template>
 
<script>
import B from "./B.vue";
export default {
  name: "A",
  components: {
    B
  },
  provide(){
    return {
      changeVal:this.changeName      //传入一个方法
    }
  },
  data(){
    return {
      obj:{
        name:"leo"
      }
    }
  },
  methods:{
    changeName(val){          //C中触发该方法执行,此时变成"lion"
      this.obj.name = val
    }
  }
};
</script>

c使用inject 继承该方法,在自己的方法内调取改方法即可

<template>
  <div>
    <span @click="changeName">点击改变A组件数据</span>
  </div>
</template>
 
<script>
export default {
  name: "C",
  inject:["changeVal"],    //接收一个方法
  methods:{
    changeName(){
      this.changeVal("lion")     //执行此方法,改变A中的数据
    }
  }
};
</script>

vue3 中的使用:

vue3:provide

在 setup() 中使用 provide 时,我们首先从 vue 显式导入 provide 方法。这使我们能够调用 provide 来定义每个 property。

provide 函数允许你通过两个参数定义 property:

  • name (<String> 类型)
  • value

使用A组件,provide 的值可以按如下方式重构:

<template>
  <C />
</template>
 
<script>
import { provide } from 'vue'
import C from './C.vue'
 
export default {
  components: {
    C
  },
  setup() {
    provide('location', 'North Pole')
    provide('geolocation', {
      longitude: 90,
      latitude: 135
    })
  }
}
</script>
vue3: inject

在 setup() 中使用 inject 时,也需要从 vue 显式导入。导入以后,我们就可以调用它来定义暴露给我们的组件方式。

inject 函数有两个参数:

要 inject 的 property 的 name
默认值 (可选)
使用C组件,可以使用以下代码对其进行重构:

<script>
import { inject } from 'vue'
 
export default {
  setup() {
    const userLocation = inject('location', 'The Universe')
    const userGeolocation = inject('geolocation')
 
    return {
      userLocation,
      userGeolocation
    }
  }
}
</script>
provide响应式

为了增加 provide 值和 inject 值之间的响应性,我们可以在 provide 值时使用 ref 或 reactive

<template>
  <C />
</template>
 
<script>
import { provide, reactive, ref } from 'vue'
import C from './C.vue'
 
export default {
  components: {
    C
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })
 
    provide('location', location)
    provide('geolocation', geolocation)
  }
}
</script>

如果需要在c中修改a中的数据,需要向provide传入一个方法

<template>
  <C />
</template>
 
<script>
import { provide, reactive, ref } from 'vue'
import C from './C.vue'
 
export default {
  components: {
    C
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })
 
    const updateLocation = () => {
      location.value = 'South Pole'
    }
 
    provide('location', location)
    provide('geolocation', geolocation)
    provide('updateLocation', updateLocation)     //传入一个方法
  }
}
</script>

c中调用该方法

<script>
import { inject } from 'vue'
 
export default {
  setup() {
    const userLocation = inject('location', 'The Universe')
    const userGeolocation = inject('geolocation')
    const updateUserLocation = inject('updateLocation')
 
    return {
      userLocation,
      userGeolocation,
      updateUserLocation      //执行该方法,触发祖先组件方法执行,从而改变数据
    }
  }
}
</script>

最后,如果要确保通过 provide 传递的数据不会被 inject 的组件更改,我们建议对提供者的 property 使用 readonly

<template>
  <C />
</template>
 
<script>
import { provide, reactive, readonly, ref } from 'vue'
import C from './C.vue'
 
export default {
  components: {
    C
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })
 
    const updateLocation = () => {
      location.value = 'South Pole'
    }
    // 使用readonly,数据只读
    provide('location', readonly(location))
    provide('geolocation', readonly(geolocation))
    provide('updateLocation', updateLocation)
  }
}
</script>


                        
参考文章:https://blog.csdn.net/qq_41809113/article/details/122071958

相关推荐

  1. vue组件传参v-bind=“$attrs“ v-on=“$listeners“

    2024-06-07 11:36:06       32 阅读
  2. vue组件通信方式介绍

    2024-06-07 11:36:06       30 阅读
  3. vue如何如何组合组件通讯

    2024-06-07 11:36:06       10 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-07 11:36:06       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-07 11:36:06       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-07 11:36:06       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-07 11:36:06       20 阅读

热门阅读

  1. linux 如何解压 zip

    2024-06-07 11:36:06       8 阅读
  2. random模块二

    2024-06-07 11:36:06       8 阅读
  3. orm 查询

    2024-06-07 11:36:06       8 阅读
  4. Kubernates-dashbord-安装

    2024-06-07 11:36:06       10 阅读
  5. ubuntu 根据 服务名(应用程序) 查 软件包名

    2024-06-07 11:36:06       8 阅读
  6. 字节跳动(校招)算法原题

    2024-06-07 11:36:06       9 阅读
  7. 工作五年后的程序员,一般怎样了?

    2024-06-07 11:36:06       7 阅读
  8. 深入理解 Spring Boot 启动原理

    2024-06-07 11:36:06       11 阅读
  9. transformers DataCollator介绍

    2024-06-07 11:36:06       8 阅读
  10. 事务 ---- mysql

    2024-06-07 11:36:06       9 阅读
  11. python的视频处理FFmpeg库使用

    2024-06-07 11:36:06       10 阅读
  12. C# 证件照替换底色与设置背景图---PaddleSegSharp

    2024-06-07 11:36:06       9 阅读