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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/23569.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在不受支持的 Mac 上安装 macOS Sonoma (OpenCore Legacy Patcher v1.5.0)

在不受支持的 Mac 上安装 macOS Sonoma (OpenCore Legacy Patcher v1.5.0) Install macOS on unsupported Macs 请访问原文链接&#xff1a;https://sysin.org/blog/install-macos-on-unsupported-mac/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主…

【leetcode--30.串联所有单词的子串】

有没有一样喜欢看示例的&#xff0c;&#xff0c;看题目就觉得很难懂。大致就是words要进行排列组合&#xff0c;返回s中所有包含这个排列组合的首标。 顺完逻辑蛮好懂的&#xff0c;应该不算困难题&#xff0c;只是不知道用什么模块实现。 class Solution:def findSubstring…

如何利用Varjo混合现实技术改变飞机维修训练方式

自2017年以来&#xff0c;总部位于休斯顿的HTX实验室一直在推进混合现实技术&#xff0c;与美国空军密切合作&#xff0c;通过其EMPACT平台提供可扩展的沉浸式飞机维护虚拟现实培训。 虚拟和混合现实对维修训练的好处&#xff1a; l 实践技能&#xff1a;提供一个非常接近真实场…

【C++题解】1074 - 小青蛙回来了

问题&#xff1a;1074 - 小青蛙回来了 类型&#xff1a;需要找规律的循环 题目描述&#xff1a; 关于小青蛙爬井的故事&#xff0c;你应该早就听过了&#xff1a;井深10 尺&#xff0c;小青蛙从井底向上爬&#xff0c;每个白天向上爬 3 尺&#xff0c;每个晚上又滑下来 2 尺&…

Java | Leetcode Java题解之第136题只出现一次的数字

题目&#xff1a; 题解&#xff1a; class Solution {public int singleNumber(int[] nums) {int single 0;for (int num : nums) {single ^ num;}return single;} }

App UI 风格,尽显魅力

精妙无比的App UI 风格

Eclipse添加C和C++编译成汇编文件的选项

在miscellaneous中添加assemble listing选项就可以生成汇编文件了

[自学记录09*]Unity Shader:在Unity里渲染一个黑洞

一、前言 记得很久很久以前&#xff0c;在ShaderToy上看过一个黑洞的效果&#xff0c;当时感觉太*8帅了&#xff0c;于是这几天就尝试自己弄了一个。 Gargantua With HDR Bloom (shadertoy.com) 下面是我自己实现的黑洞 可以看到还是略逊一筹&#xff08;感觉略逊百筹&#x…

什么是容器技术

容器虚拟化技术是一种有效的将单个操作系统的资源划分到独立的组中的技术&#xff0c;以便更好地在独立的组之间平衡有冲突的资源使用需求。这种技术通过“伪造”操作系统的接口&#xff0c;将函数库层以上的功能置于操作系统上&#xff0c;从而实现应用程序级别的虚拟化。容…

07-指针的概念与引用,索引

指针的概念与引用&#xff0c;索引 一、内存地址 字节&#xff1a; 定义&#xff1a; 字节&#xff08;byte&#xff09;是内存容量的一个单位&#xff0c;一个字节包含8个位&#xff08;bit&#xff09;。 地址&#xff1a; 定义&#xff1a; 内存地址是系统为了方便区分…

Java 主键生成策略之雪花算法

概述 项目中为了缓解数据库服务器压力和提高并发量进行分库分表,在新增数据时,如果此时按照传统方式使用数据库主键自增,那么在并发下ID可能会冲突; 使用UUID的话又因其无序会产生页分裂导致磁盘IO过大使得系统性能降低; 经过了解雪花算法根据其特点可以解决分布式系统中生成…

DockerCompose中部署Jenkins(Docker Desktop在windows上数据卷映射)

场景 DockerJenkinsGiteeMaven项目配置jdk、maven、gitee等拉取代码并自动构建以及遇到的那些坑&#xff1a; DockerJenkinsGiteeMaven项目配置jdk、maven、gitee等拉取代码并自动构建以及遇到的那些坑_jenkins的安装以及集成jdkgitmaven 提示警告-CSDN博客 Windows10(家庭版…

AI学习指南机器学习篇-逻辑回归正则化技术

AI学习指南机器学习篇-逻辑回归正则化技术 在机器学习领域&#xff0c;逻辑回归是一种常见的分类算法&#xff0c;它常用于处理二分类问题。在实际的应用中&#xff0c;为了提高模型的泛化能力和降低过拟合风险&#xff0c;逻辑回归算法通常会使用正则化技术。本文将介绍逻辑回…

待定待定待定

BindingNavigator C# 属性&#xff08;Property&#xff09; get set StringBuilder https://www.bilibili.com/video/BV15u4y1F72C/ C# 高级数据结构有哪些 List - 动态数组&#xff0c;可以动态增长和缩减&#xff0c;提供快速访问、添加和删除元素的功能。Dictionary<TK…

c#vb代码互转工具

下载地址&#xff1a; https://download.csdn.net/download/wgxds/88979921

EN 17104-2021室内用热塑性硬质保护墙板CE认证

室内用热塑性硬质保护墙板是指由同材质或非均质塑料板制成的&#xff0c;表面有或者没有装饰层&#xff0c;用于墙体的保护作用而非起结构作用&#xff0c;通过胶粘剂粘贴安装。 EN 17104-2021室内用热塑性硬质保护墙板CE认证项目 认证项目 测试标准 防火 EN 13501-1 挥发…

stm32中如何实现EXTI线 0 ~ 15与对应IO口的配置呢?

STM32的EXTI控制器支持19 个外部中断/ 事件请求。每个中断设有状态位&#xff0c;每个中断/ 事件都有独立的触发和屏蔽设置。 STM32的19个外部中断对应着19路中断线&#xff0c;分别是EXTI_Line0-EXTI_Line18&#xff1a; 线0~15&#xff1a;对应外部 IO口的输入中断。 线16&…

【MMU】——ARM 一级页表

文章目录 一级页表项即 entry 的格式如下 从上图可以看出 L1 页表项有四种可能类型 产生中止异常的故障条目。这可能是预取或数据中止、取决于访问类型。这实际上表示虚拟地址未映射 bit[1:0] = 00指向 L2 转换表的条目。这样就能将 1MB 的内存分页 bit[1:0] = 01。1MB 段转换…

STM32远程更新

1 IAP 概述 1.1 工作原理 在应用中编程&#xff08; IAP &#xff09;是一种在现场通过 MCU 的通信接口&#xff08;例如 UART,USB,CAN 和以太网 等&#xff09;进行固件升级的方式。 当启动微控制器时&#xff0c;您可以选择让它进入 IAP 模式以执行 IAP 代码&am…

Linux-用户管理与软件管理

用户授权 如果普通用户需要执行特殊操作&#xff0c;有两种方法 1、su - root 切换到root账号进行特殊操作&#xff0c;然后再返回到普通用户 2、sudo命令 命令&#xff1a;su 优点&#xff1a;使用简单 缺点&#xff1a;1、root密码容易泄露&#xff1b;2、普通用…