Vue3中的常见组件通信之`provide`、`inject`

Vue3中的常见组件通信之provideinject

概述

​ 在vue3中常见的组件通信有props、mitt、v-model、 r e f s 、 refs、 refsparent、provide、inject、pinia、slot等。不同的组件关系用不同的传递方式。常见的撘配形式如下表所示。

组件关系传递方式
父传子1. props
2. v-model
3. $refs
4. 默认插槽、具名插槽
子传父1. props
2. 自定义事件
3. v-model
4. $parent
5. 作用域插槽
祖传孙、孙传祖1. $attrs
2. provide、inject
兄弟间、任意组件间1. mitt
2. pinia

props和自定义事件详见:
Vue3中的常见组件通信之props和自定义事件

mitt用法详见:
Vue3中的常见组件通信之mitt

v-model用法详见:
Vue3中的常见组件通信之v-model

$attrs用法详见:
Vue3中的常见组件通信之$attrs

$refs$parent详见:
Vue3中的常见组件通信之$refs$parent

接下来是provide和inject。

7.provide和inject

provideinject用于当前组件向其后代组件直接通信,需要先在祖先组件中通过provide配置向后代组件提供数据,然后在后代组件中通过inject配置声明接收数据。

7.1准备三个组件

先准备三个组件,分别为父组件、子组件和孙组件,具体代码如下:

父组件代码:

<template>
  <div class="father">
    <h3>父组件</h3>
    <h4>用户订单详情</h4>
    <ul>
      <li>订单编号:{{ oderDetail.id }}</li>
      <li>订单用户:{{ oderDetail.username }}</li>
      <li>订单商品:{{ oderDetail.goods }}</li>
      <li>订单价格:{{ oderDetail.price }}</li>
    </ul>
    <Child/>
  </div>
</template>

<script lang="ts" setup name="Father">
import Child from './Child.vue'
import {reactive} from 'vue'

let oderDetail = reactive({
  id:"abc01",
  username:'xiaopeng',
  goods:"神仙水",
  price:998
})
</script>

<style scoped>
  .father{
    background-color: rgb(112, 150, 66);
    margin: 10px;
    padding: 10px;
    border-radius: 5px;
  }
</style>

子组件代码:

<template>
  <div class="child">
    <h3>子组件</h3>
    <GrandChild/>
  </div>
</template>

<script lang="ts" setup name="Child">
  import GrandChild from './GrandChild.vue'

</script>

<style scoped>
  .child{
    background-color: burlywood;
    margin: 10px;
    padding: 10px;
    border-radius: 10px;
  }
</style>

孙组件代码:

<template>
  <div class="grandChild">
    <h3>
      这是孙组件
    </h3>
  </div>
</template>

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

</script>

<style scoped>
  .grandChild{
    background-color: aqua;
    margin: 10px;
    padding:10px;
    border-radius: 5px;
  }
</style>

运行效果如下:

image-20240609172455063

7.2 祖传孙通信的实现

在父组件中引入provide,并提供数据

import {reactive,provide} from 'vue'
//提供数据
provide('oderDetail',oderDetail)

注意此处第一个参数的名字可以是任意的,第二个参数为数据,如果是多个数据,可以为对象格式的数据。

在后代组件中(以孙组件为例)引入inject,并注入数据:

import { inject } from 'vue';

//注入数据
let oderDetail = inject('oderDetail')

注意inject中的第一个参数必须与祖组件中provide中第一个参数相同,第二个参数为默认值,即当父组件中没有传递'oderDetail',那么孙组件中的oderDetail的值就是procide中的第二个参数。

孙组件中在页面中呈现:

<h4>父组件传递过来的用户订单详情</h4>
    <ul>
      <li>订单编号:{{ oderDetail.id }}</li>
      <li>订单用户:{{ oderDetail.username }}</li>
      <li>订单商品:{{ oderDetail.goods }}</li>
      <li>订单价格:{{ oderDetail.price }}</li>
    </ul>

注意上面代码中VS Code进行TS检查,会提示oderDetail有错误,但是实际不影响页面呈现,运行结果如下:

image-20240609233257739

接下来需要处理ts的问题,ts显示oderDetail类型为未知,那么可以在定义oderDetail的时候给个默认值,如下代码:

let oderDetail = inject('oderDetail',{id:'',username:'',goods:'',price:0})

此时VS Code就不再报错,并且运行结果一样。

7.3 孙传祖通信的实现

provide和inject也可以实现孙传祖通信,需要在父组件中定义一个函数,并传递给后代:

//方法
function discount(value:number){
  oderDetail.price = oderDetail.price * value/10
}
//提供方法
provide('discount',discount)

孙组件中接收方法:

let discount = inject('discount',(value:number)=>{})

孙组件中添加按钮并绑定单击事件触发接收的方法,并传递参数:

<button @click="discount(7)">父组件中的订单价格打7折</button>

运行后单击按钮可以实现更改父组件中的价格,由于孙组件中接收的数据为相应式的,因此更改父组件中的价格,孙组件中的订单价格也会相应变化,如下图所示:

至此以及实现了孙传祖通信。

不过上面代码还可以简化,之前提到过provide第二个参数如果是多个数据,可以为对象格式的数据,这样就可以把数据和对象同时传递和接收,如下代码所示:

//提供数据和方法
provide('oderContent',{oderDetail,discount})
let {oderDetail,discount} = inject('oderContent',{oderDetail:{id:'',username:'',goods:'',price:0},discount:(value:number)=>{}})

这样运行的结果是完全一样的。

7.4 小结

provideinject用于当前组件向其后代组件直接通信,需要先在祖先组件中通过provide配置向后代组件提供数据,然后在后代组件中通过inject配置声明接收数据。这个过程是完全不打扰中间的子组件,实现的是祖孙间的直接通信。

下面是完整代码:

父组件:

<template>
  <div class="father">
    <h3>父组件</h3>
    <h4>用户订单详情</h4>
    <ul>
      <li>订单编号:{{ oderDetail.id }}</li>
      <li>订单用户:{{ oderDetail.username }}</li>
      <li>订单商品:{{ oderDetail.goods }}</li>
      <li>订单价格:{{ oderDetail.price }}</li>
    </ul>
    <Child/>
  </div>
</template>

<script lang="ts" setup name="Father">
import Child from './Child.vue'
import {reactive,provide} from 'vue'

//数据
let oderDetail = reactive({
  id:"abc01",
  username:'xiaopeng',
  goods:"神仙水",
  price:998
})

//方法
function discount(value:number){
  oderDetail.price = oderDetail.price * value/10
}
// //提供数据
// provide('oderDetail',oderDetail)
// 提供方法
// provide('discount',discount)

//提供数据和方法
provide('oderContent',{oderDetail,discount})

</script>

<style scoped>
  .father{
    background-color: rgb(112, 150, 66);
    margin: 10px;
    padding: 10px;
    border-radius: 5px;
  }
</style>

子组件:

<template>
  <div class="child">
    <h3>子组件</h3>
    <GrandChild/>
  </div>
</template>

<script lang="ts" setup name="Child">
  import GrandChild from './GrandChild.vue'

</script>

<style scoped>
  .child{
    background-color: burlywood;
    margin: 10px;
    padding: 10px;
    border-radius: 10px;
  }
</style>

孙组件:

<template>
  <div class="grandChild">
    <h3>
      这是孙组件
    </h3>
    <h4>父组件传递过来的用户订单详情</h4>
    <ul>
      <li>订单编号:{{ oderDetail.id }}</li>
      <li>订单用户:{{ oderDetail.username }}</li>
      <li>订单商品:{{ oderDetail.goods }}</li>
      <li>订单价格:{{ oderDetail.price }}</li>
    </ul>
    <button @click="discount(7)">父组件中的订单价格打7折</button>
  </div>
</template>

<script lang="ts" setup name="GrandChild">
import { inject } from 'vue';

// // 注入数据
// let oderDetail = inject('oderDetail',{id:'',username:'',goods:'',price:0})
// let discount = inject('discount',(value:number)=>{})

let {oderDetail,discount} = inject('oderContent',{oderDetail:{id:'',username:'',goods:'',price:0},discount:(value:number)=>{}})

</script>

<style scoped>
  .grandChild{
    background-color: aqua;
    margin: 10px;
    padding:10px;
    border-radius: 5px;
  }
</style>

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

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

相关文章

大数据的力量:推动战略决策和业务转型

在当前全球化的时代背景下&#xff0c;国际间的联系日益紧密&#xff0c;世界变得更加互联互通。面对各种危机&#xff0c;数据驱动决策和分析显得愈发重要。从医学研究到市场趋势分析&#xff0c;大数据技术在各个领域发挥着关键作用&#xff0c;推动着一场深刻的变革浪潮。 大…

关于伪标头那些事

前言 看到伪标头&#xff0c;不少同学可能会比较陌生&#xff0c;因为谁让它默默无闻呢&#xff1f; 当然博主把它比喻为一个来自传输层的“共享盒子”。提到共享&#xff0c;我想大家有所体会了。这里给大家贴一张直观的图例&#xff0c;可以静静观摩之。 Q&#xff1a;什么是…

高端品牌网站建设

随着互联网的快速发展&#xff0c;越来越多的企业开始意识到高端品牌网站建设对于企业发展的重要性。高端品牌网站建设不仅是企业形象展示的窗口&#xff0c;更是与消费者进行有效沟通和互动的桥梁。下面从设计、内容和用户体验三个方面&#xff0c;探讨高端品牌网站建设的重要…

使用代理IP常见问题有哪些?

代理IP在互联网数据收集和业务开展中发挥着重要作用&#xff0c;它充当用户客户端和网站服务器之间的“屏障”&#xff0c;可以保护用户的真实IP地址&#xff0c;并允许用户通过不同的IP地址进行操作。然而&#xff0c;在使用代理IP的过程中&#xff0c;用户经常会遇到一些问题…

php遇到的问题

1、 underfined at line 3 in xxx.php , 错误提示&#xff0c;注释这行代码 // error_reporting(DEBUG ? E_ALL : 0); 目录&#xff1a;config/config.php

爆火的“植物大战僵尸杂交版” ‍♂️【附带安装包】

一、 杂交版植物引言 什么&#xff01;你不会还没听过最近爆火的 《植物大战僵尸杂交版》吧&#xff1f;&#xff01;&#xff1f;&#xff01; 下面这些植物你是否未曾见过&#xff0c;或者已经非常熟悉呢&#xff1f; 二、&#x1f331;&#x1f9df;‍♂️ **杂交版介绍** &…

探索C嘎嘎的奇妙世界:第三关---缺省参数与函数重载

在c语言中,我们常常在对有参函数进行传参,这样的繁琐过程,C祖师爷对此进行了相关改进,多说无益,上干货: 1 缺省参数: 缺省参数是指在声明或定义函数时为函数的形参指定一个默认值&#xff08;默认参数&#xff09;。在调用该函数时&#xff0c;如果没有指定实参&#xff0c;则…

2376.统计特殊整数

链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int countSpecialNumbers(int n) {if (n < 0) {return -1;}std::string str to_string(n);std::vector<std::vector&l…

东南亚短视频:四川鑫悦里文化传媒有限公司

东南亚短视频&#xff1a;探寻异域的魅力与风情 随着短视频平台的兴起&#xff0c;世界各地的风土人情得以通过屏幕展现在我们眼前。而东南亚&#xff0c;这片充满异域魅力的土地&#xff0c;更是成为了短视频创作者们争相探索的热门目的地。今天&#xff0c;就让四川鑫悦里文…

【源码】2024运营版多商户客服系统/在线客服系统/手机客服/PC软件客服端

带客服工作台pc软件源代码&#xff0c;系统支持第三方系统携带参数打开客服链接&#xff0c;例如用户名、uid、头像等 支持多商家&#xff08;多站点&#xff09;支持多商家&#xff08;多站点&#xff09;&#xff0c;每个注册用户为一个商家&#xff0c;每个商家可以添加多个…

element-ui tabs+table 实现点击表格切换标签页

客户需求&#xff1a;点击主任务标签页中的表格 跳转到子任务所在的标签页 代码&#xff1a; 表格部分&#xff1a; <el-tabs type"border-card" :active-name"currentTab" tab-click"handleTabClick"><el-tab-pane class"table…

Fastjson漏洞之CVE-2022-25845

前言&#xff1a; 针对Fastjson之前已经介绍了&#xff0c;这里就不再重复了&#xff0c;漏洞CVE-2017-18349只能用来攻击>1.2.24版本的&#xff0c;CVE-2022-25845属于CVE-2017-18349的升级版&#xff0c;但是目前仅影响到1.2.83以下版本。CVE-2022-25845本质上是绕过了名…

理解并应用:JavaScript响应式编程与事件驱动编程的差异

背景介绍 在现代JavaScript开发中&#xff0c;响应式编程&#xff08;Reactive Programming&#xff09;和事件驱动编程&#xff08;Event-Driven Programming&#xff09;是两种非常重要且常用的编程范式。虽然它们都用于处理异步操作&#xff0c;但在理念和实现方式上存在显…

2 程序的灵魂—算法-2.4 怎样表示一个算法-2.4.2 用流程图表示算法-【例 2.9】

将例 2.4 求 1-1/21/3-1/41/99-1/100 的算用流程图表示。 一个流程图包括&#xff1a; 1. 表示相应操作的框&#xff1b; 2. 带箭头的流程线&#xff1b; 3. 框内外必要的文字说明。

Canvas倒计时

Canvas倒计时 前言 用Canvas绘制一个倒计时组件&#xff0c;显示距离新年还有多长时间&#xff0c;精确到秒&#xff0c;该倒计时需要实时更新 基础知识点 JS Date() 创建一个新Date对象的唯一方法是通过new 操作符&#xff0c;例如&#xff1a;let now new Date(); 若将…

Unity API学习之资源的动态加载

资源的动态加载 在实际游戏开发的更新换代中&#xff0c;随着开发的软件不断更新&#xff0c;我们在脚本中需要拖拽赋值的变量会变空&#xff0c;而要想重新拖拽又太花费时间&#xff0c;因此我们就需要用到Resources.Load<文件类型>("文件名")函数来在一开始…

R3CTF NinjaClub复现

R3CTF NinjaClub jinjia2沙箱 题目源码 from jinja2.sandbox import SandboxedEnvironment, is_internal_attribute from jinja2.exceptions import UndefinedError from fastapi import FastAPI, Form from fastapi.responses import HTMLResponse from pydantic import Bas…

MicroPython+ESP32 C3开发上云

传感器PinI/O状态D412输出1开0关D513输出1开0关 概述 MicroPython是python3编程语言的精简实现&#xff0c;能够在资源非常有限的硬件上运行&#xff0c;如MCU微控制器Micropython的网络功能和计算功能很强大&#xff0c;有非常多的库可以使用&#xff0c;它为嵌入式开发带来了…

线程池监控是怎么做的?

引言&#xff1a;在现代软件开发中&#xff0c;线程池是一种重要的并发控制机制&#xff0c;它能有效管理和复用线程资源&#xff0c;提升系统的性能和响应速度。然而&#xff0c;随着应用规模的扩大和复杂性的增加&#xff0c;对线程池进行有效监控显得尤为重要。线程池监控不…

CentOS搭建kubernetes集群详细过程(yum安装方式)

kubernetes集群搭建详细过程&#xff08;yum安装方式&#xff09; Kubernetes&#xff0c;也被称为K8s&#xff0c;是一个多功能的容器管理工具&#xff0c;它不仅能够协调和调度容器的部署&#xff0c;而且还能监控容器的健康状况并自动修复常见问题。这个平台是在谷歌十多年…