组件通信——provide 和 inject 实现爷孙组件通信

provide 和 inject 实现爷孙组件通信

介绍

provideinject 是 Vue.js 提供的一种在组件之间共享数据的机制,它允许在组件树中的任何地方注入依赖项。这对于跨越多个层级的组件间通信特别有用,因此无需手动将 prop 数据逐层传递下去。

  • provide

    • 在一个组件中使用 provide 方法来定义要提供的数据或方法。

    • provide 方法返回一个对象,该对象包含了要提供的数据或方法。

  • inject

    • 在另一个组件中使用 inject 方法来注入这些数据或方法。

    • inject 方法接收一个数组或对象,指明要注入的数据或方法名称。

实现原理

provide 方法

当你在组件中定义 provide 方法时,Vue.js 会执行以下步骤:

  • 创建 provide 对象:
provide() {
 return {
   sharedData: 'Hello from App component!',
   updateData: this.updateData
 };
}
  • 附加到组件实例:Vue.js 会在组件实例上附加一个 _provided 属性,存储 provide 方法返回的对象。

inject 方法

当你在组件中定义 inject 方法时,Vue.js 会执行以下步骤:

  • 查找 provide 对象:Vue.js 会从当前组件及其祖先组件中查找 _provided 属性。
    如果找到,则将相应的数据或方法注入到当前组件中。

  • 注入到组件实例:注入的数据或方法会作为属性添加到当前组件实例上,可以通过 this 访问。

优点
  • 简化多层级组件通信:不需要逐层传递 props,可以方便地在组件树中的任意位置提供和注入数据。

  • 灵活性高:可以动态地提供和注入数据或方法,适用于多种场景。

  • 减少代码冗余:减少了逐层传递 props 的代码量,提高了代码的可读性和可维护性。

缺点
  • 调试困难:由于数据传递路径不明确,调试时可能比较困难,尤其是在大型项目中。

  • 组件关系模糊:组件之间的依赖关系变得不清晰,可能导致代码难以理解和维护。

  • 性能开销:大量使用 provideinject 可能导致额外的性能开销,特别是在复杂的应用中。

  • 滥用问题:如果过度使用 provideinject,可能会导致组件之间的耦合度过高,降低代码的可维护性。

vue2.x 使用

grandpa.vue 组件(爷)

  • 使用 provide 方法提供了 message, message2 字符串和一个 sendGradpaMessage 方法。

  • sendGradpaMessage 方法用于接收子组件传递的消息。

// grandpa.vue

<template>
  <div class="grandpa">
    <h2>爷组件</h2>
    <parent />
  </div>
</template>

<script>
import parent from './parent.vue';

export default {
  name: 'grandpa',
  data() {
    return {

    }
  },
  provide() {
    return {
      message: 'This is some shared data1',
      message2: 'This is some shared data2',
      sendGradpaMessage: this.getSendMessage
    };
  },
  components: {
    parent
  },
  methods: {
    getSendMessage(message) {
      console.log('Message received:', message);
    }
  }
}
</script>

parent.vue 组件(父)

  • 使用 inject 方法注入了从爷组件提供的 message 参数。
// parent.vue

<template>
  <div class="parent">
    <h2>父组件</h2>
    <span>{{ message }}</span>
    <son />
  </div>
</template>

<script>
import son from './son.vue';

export default {
  name: 'parent',
  data() {
    return {

    }
  },
  inject: ['message'],
  components: { son },
  methods: {
   
  }
}
</script>

son.vue 组件(子)

  • 使用 inject 方法注入了从爷组件提供的 message2 字符串和一个 sendGradpaMessage 方法。

  • 当点击按钮时,调用 sendGradpaMessage 方法将消息传递给祖先组件。

// son.vue

<template>
  <div class="son">
    <h2>孙组件</h2>
    <span>{{ message2 }}</span>
    <el-button type="primary" @click="sendMessage">发送消息</el-button>
  </div>
</template>

<script>
export default {
  name: 'son',
  data() {
    return {

    }
  },
  inject: ['message2', 'sendGradpaMessage'],

  methods: {
    sendMessage() {
      const msg = 'Hello from son component!';
      this.sendGradpaMessage(msg);
    }
  }
}
</script>

上述示例中:

  • grandpa.vue 组件通过 provide 方法提供了 message, message2 两个参数和一个名为 sendGradpaMessage 的方法。

  • parent.vue 组件通过 inject 接收了 message 参数,并在模板中使用 message

  • son.vue 组件通过 inject 接收了 message2 参数,并在模板中使用 message,同时通过点击按钮触发 sendGradpaMessage 方法将参数 msg 传给了 grandpa.vue 组件。

类型检查

inject 的配置项可以是一个数组或者一个对象。当使用对象形式时,可以指定更多的配置选项,比如类型检查、默认值等。

配置选项详解

  • from:指定 inject 要注入的数据的键名。如果没有指定,则默认为 inject 的键名。

  • default:如果没有从祖先组件中找到对应的数据,则使用这个默认值。这对于确保组件即使在缺少某些数据的情况下也能正常工作是非常有用的。

  • fromdefault 的组合:你可以同时指定 from 和 default,在这种情况下,如果 from 指定的数据不存在,则使用 default 中定义的值。

例如,你可以指定默认值和别名:

inject: {
 // 定义别名为 message2 的数据,其来源为 message2
  message2: {   
    from: 'message2',
     // 如果没有提供则使用默认值
    default: 'Default value if not provided'
  },
  // 定义别名为 sendGradpaMessage 的方法
  sendGradpaMessage: {
    from: 'sendGradpaMessage',
    // 如果没有提供则使用一个空函数作为默认值
    default: () => {}
  }
}

vue3.x 使用

在 Vue 3.x 中,provideinject 的使用方式有所变化,主要是因为引入了 Composition API。在 Composition API 中,provideinject 的使用更加灵活,并且通常在 setup 函数中进行操作。

注意事项:

1. Composition API 中的使用:

  • 在 Vue 3.x 中,provide 和 inject 必须在 setup 函数中使用。

  • provide 通常用来向子组件提供数据或方法。

  • inject 用来从父组件或其他祖先组件获取数据或方法。

2. 响应式处理:

  • 当使用 provide 提供一个响应式对象时,Vue 3.x 会自动处理它的响应性。然而,如果提供的数据不是响应式的,那么注入的数据也不会是响应式的。

3. 类型安全:

  • 在 TypeScript 项目中,可以使用类型注解来确保 provide 和 inject 的类型安全。

4. 默认值:

  • 在 Vue 3.x 中,inject 可以接受一个默认值作为第二个参数,如果找不到对应的 provide 数据,则使用默认值。

5. 调试:

  • 使用 provide 和 inject 时,确保在开发过程中使用 Vue Devtools 来帮助跟踪数据流。
示例

grandpa.vue 组件(爷)

  • 使用 provide 方法提供了 message, message2 字符串和一个 sendGradpaMessage 方法。

  • sendGradpaMessage 方法用于接收子组件传递的消息。

// grandpa.vue

<template>
  <div class="grandpa">
    <h2>爷组件</h2>
    <div>{{ num1 }}</div>

    <parent />
  </div>
</template>

<script setup lang="ts" name="grandpa">
import { provide, ref } from 'vue';

import parent from './parent.vue';

// 定义一个可变的值
const message = ref('Hello from grandpa');
const message2 = ref('Hello from Parent');

let num1 = ref(0);
// 使用 provide 将这个值暴露给子组件
provide('message', message);
provide('message2', message2);
provide('sendGradpaMessage', getSendMessage);

// 接受 son 组件传递的参数
function getSendMessage(num: number) {
  console.log('msg::: ', num);
  num1.value = num
}
</script>

parent.vue 组件(父)

  • 使用 inject 方法注入了从爷组件提供的 message2 参数。
// parent.vue

<template>
  <div class="parent">
    <h2>父组件</h2>
    <span>{{ message2 }}</span>
    <son />
  </div>
</template>

<script setup lang="ts" name="parent">
import son from './son.vue';
import { inject, onMounted } from 'vue';


// 使用 inject 获取父组件提供的值
const message2 = inject('message2');
</script>

son.vue 组件(子)

  • 使用 inject 方法注入了从爷组件提供的 message2 字符串和一个 sendGradpaMessage 方法。

  • 当点击按钮时,调用 sendGradpaMessage 方法将消息传递给祖先组件。

// son.vue

<template>
  <div class="son">
    <h2>孙组件</h2>
    <div>{{ message }}</div>
    <el-button type="primary" @click="sendMessage(111)">发送消息</el-button>
  </div>
</template>

<script setup lang="ts" name="son">

import { inject, onMounted } from 'vue';

// 使用 inject 获取父组件提供的值
const message = inject('message', '默认值');

const sendMessage = inject('sendGradpaMessage', (params: number) => { });

</script>

上述示例中:

  • grandpa.vue 组件通过 provide 方法提供了 message, message2 两个参数和一个名为 sendGradpaMessage 的方法。

  • parent.vue 组件通过 inject 接收了 message 参数,并在模板中使用 message

  • son.vue 组件通过 inject 接收了 message2 参数,并在模板中使用 message,同时通过点击按钮触发 sendGradpaMessage 方法将参数 msg 传给了 grandpa.vue 组件。

总结

provideinject 是 Vue.js 中一种用于跨越多个层级组件间通信的机制,通过在组件中定义 provide 方法提供数据或方法,并在其他组件中使用 inject 方法注入这些数据或方法,从而简化了多层级组件间的通信。这种方式不仅减少了逐层传递 props 的代码量,提高了代码的可读性和可维护性,还支持动态提供和注入数据,适用于多种场景。然而,过度使用 provideinject可能会导致组件之间的耦合度增加,影响代码的调试和维护。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

长沙自闭症寄宿学校推荐,为孩子开启光明未来

在长沙这座历史悠久而又充满活力的城市中&#xff0c;自闭症儿童的成长与教育问题牵动着无数家庭的心。家长们渴望为孩子找到一所能够提供专业康复、温馨关怀与全面教育的学校&#xff0c;为他们的未来铺设一条光明之路。虽然本文起始于长沙的期盼&#xff0c;但我们的目光已跨…

SpringSecurity原理解析(二):认证流程

1、SpringSecurity认证流程包含哪几个子流程&#xff1f; 1&#xff09;账号验证 2&#xff09;密码验证 3&#xff09;记住我—>Cookie记录 4&#xff09;登录成功—>页面跳转 2、UsernamePasswordAuthenticationFilter 在SpringSecurity中处理认证逻辑是在UsernamePas…

Windows10 如何配置python IDE

Windows10 如何配置python IDE 前言Python直接安装&#xff08;快速上手&#xff09;Step1.找到网址Step2.选择版本&#xff08;非常重要&#xff09;Step3. 安装过程Step4. python测试 Anaconda安装&#xff08;推荐&#xff0c;集成了Spyder和Pycharm的安装&#xff09;Step1…

使用功率分析仪测量和分析电抗器(电感器)的方法

高频电抗器用于电动汽车 (EV) 和混合动力汽车 (HEV) 的各种位置。例如&#xff0c;电池和逆变器之间的升压 DC/DC 转换器以及电池充电电路中的 AC/DC 转换器。为了提高整个系统的效率&#xff0c;必须提高每个组成电路的效率&#xff0c;而电抗器是造成这些电路大量损耗的元件之…

Unity 之 【Android Unity FBO渲染】之 [Unity 渲染 Android 端播放的视频] 的一种方法简单整理

Unity 之 【Android Unity FBO渲染】之 [Unity 渲染 Android 端播放的视频] 的一种方法简单整理 目录 Unity 之 【Android Unity FBO渲染】之 [Unity 渲染 Android 端播放的视频] 的一种方法简单整理 一、简单介绍 二、FBO 简单介绍 三、案例实现原理 四、注意事项 五、简…

03 Flask-添加配置信息

回顾之前学习的内容 02 Flask-快速上手 Flask 中最简单的web应用组成 1. 导入核心库 Flask from flask import Flask2. 实例化 web应用 注意&#xff1a;不要漏了 app Flask(__name__) 中的 __name__ 表示&#xff1a;是从当前的py文件实例化 app Flask(__name__)3. 创…

力扣每日一题:1372.二叉树中的最长交错路径

题目 给你一棵以 root 为根的二叉树&#xff0c;二叉树中的交错路径定义如下&#xff1a; 选择二叉树中 任意 节点和一个方向&#xff08;左或者右&#xff09;。如果前进方向为右&#xff0c;那么移动到当前节点的的右子节点&#xff0c;否则移动到它的左子节点。改变前进方…

力扣213-打家劫舍 II(Java详细题解)

题目链接&#xff1a;213. 打家劫舍 II - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 本体是打家劫舍的一个变形题&#xff0c;希望大家能先做198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09;&#xff0c;并看一下我上题的讲解力扣198-打家劫舍&…

制证书、制电子印章、签章 -- 演示程序说明

ofd签章系统涉及证书的制作、电子印章制作、签章、验章等环节。关于ofd签章原理&#xff0c;本人写过多篇文章进行了阐述; 见文章《ofd板式文件 电子签章实现方法》、《一款简单易用的印章设计工具》、《签章那些事 -- 让你全面了解签章的流程》。 为了进一步加深对签章过程的理…

RK3229 ADNROID9 hdmi与耳机口同出声音

声卡0怎么配置才能跟HDMI同时输出一样的声音&#xff0c;下面是具体描述&#xff1a; 1、硬件连接 声卡0的连接是芯片的ADC音频输出脚直接接到DA芯片输出 2、cat /proc/asound/cards 0 [rockchiprk3229 ]: rockchip_rk3229 - rockchip,rk3229 rockchip,rk3229 1 [rockchiphdmi …

MFC工控项目实例之十一板卡测试信号输入界面

承接专栏《MFC工控项目实例之十添加系统测试对话框》 相关代码 1、在BoardTest.h文件中添加代码 class CBoardTest : public CDialog { // Construction public:CBoardTest(CWnd* pParent NULL); // standard constructorCButtonST m_btnStart[16];CWinThread* pThread…

FAT32文件系统详细分析 (格式化SD nandSD卡)

FAT32 文件系统详细分析 (格式化 SD nand/SD 卡) 目录 FAT32 文件系统详细分析 (格式化 SD nand/SD 卡)1. 前言2.格式化 SD nand/SD 卡3.FAT32 文件系统分析3.1 保留区分析3.1.1 BPB(BIOS Parameter Block) 及 BS 区分析3.1.2 FSInfo 结构扇区分析3.1.3 引导扇区剩余扇区3.1.4 …

RocketMQ 基础入门

文章内容是学习过程中的知识总结&#xff0c;如有纰漏&#xff0c;欢迎指正 文章目录 前言 RocketMQ 特点 RocketMQ 优势 1. RocketMQ 基本概念 1.1 NameServer 1.1.1 NameServer作用 1.1.2 和zk的区别 1.1.3 高可用保障 1.2 Broker 1.2.1 部署方式 1.2.1.1 单 Master 1.2.1.2 …

C语言 | Leetcode C语言题解之第396题旋转函数

题目&#xff1a; 题解&#xff1a; #define MAX(a, b) ((a) > (b) ? (a) : (b))int maxRotateFunction(int* nums, int numsSize){int f 0, numSum 0;for (int i 0; i < numsSize; i) {f i * nums[i];numSum nums[i];}int res f;for (int i numsSize - 1; i &g…

多维时序 | Matlab基于SSA-SVR麻雀算法优化支持向量机的数据多变量时间序列预测

多维时序 | Matlab基于SSA-SVR麻雀算法优化支持向量机的数据多变量时间序列预测 目录 多维时序 | Matlab基于SSA-SVR麻雀算法优化支持向量机的数据多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于SSA-SVR麻雀算法优化支持向量机的数据多变…

Docker部署tenine实现后端应用的高可用与负载均衡

采用Docker方式的Tengine 和 keepalived 组合模式可以实现小应用场景的高可用负载均衡需求 目录 网络架构一、环境准备二、软件安装1. 下载Tenine镜像2. 下载Keepalived镜像3. 制作SpringBoot镜像 三、软件配置1. 创建应用容器2. 代理访问应用3. 创建Keepalived4. 测试高可用 网…

CSP-J算法基础 树状结构与二叉树

文章目录 前言树状结构树状结构的基本概念&#xff1a;为什么需要树状结构&#xff1f;优点树状结构的示例 二叉树什么是二叉树&#xff1f;二叉树的类型什么样的树不是二叉树&#xff1f;二叉树的五种形态 完全二叉树相关概念完全二叉树的定义&#xff1a; 相关概念1. **高度&…

Xcode报错:No exact matches in reference to static method ‘buildExpression‘

Xcode报错1&#xff1a;No exact matches in reference to static method buildExpression Xcode报错2&#xff1a;Type () cannot conform to View 这两个报错都是因为在SwiftUI的View的Body里面使用了ForEach循环,却没有在ForEach循环闭包的内部返回视图&#xff0c;而是做了…

数据库安全性控制

‍ 在当今信息化时代&#xff0c;数据库安全性 对于保护数据免受非法访问和损害至关重要。无论是个人数据还是企业机密&#xff0c;数据库安全性控制都能有效地防范潜在的威胁。本文将为你深入浅出地介绍数据库安全性控制的关键方法和机制&#xff0c;帮助你轻松掌握这一重要概…

数据库基础知识---------------------------(1)

数据库分类 关系型数据库 以表格方式存储数据 例子&#xff1a; MySQL、Oracle、DB2、SQLserver等 特点&#xff1a; SQL结构程度较高、安全性高、查询效率较低 非关系型数据库 以键值方式存储数据 例子&#xff1a; Redis、Hbase、MongoDB等 特点&#xff1a; 查询效率…