Vue3 依赖注入provide与inject

news/2024/7/5 3:59:31

简介

        关于provide与inject下面是vue官网上的一些介绍

        通常情况下,当我们需要从父组件向子组件传递数据时,会使用props。想象一下这样的结构:有一些多层级嵌套的组件,形成了一颗巨大的组件树,而某个深层的子组件需要一个较远的祖先组件中的部分数据。在这种情况下,如果仅使用 props 则必须将其沿着组件链逐级传递下去,这会非常麻烦:

       

注意,虽然这里的 <Footer> 组件可能根本不关心这些 props,但为了使 <DeepChild> 能访问到它们,仍然需要定义并向下传递。如果组件链路非常长,可能会影响到更多这条路上的组件。这一问题被称为“prop 逐级透传”,显然是我们希望尽量避免的情况。

provide 和 inject 可以帮助我们解决这一问题 [1]。一个父组件相对于其所有的后代组件,会作为依赖提供者。任何后代的组件树,无论层级有多深,都可以注入由父组件提供给整条链路的依赖。

一个小栗子 

        创建一个跟组件,跟组件提供了三个数据源:let message、const mesRef、const mesReactive,后两者为ref、reactive类型的值,代码如下:

<template>
  <div class="box">
    <div class="show">第一层组件显示的message的值:{{ message }}</div>
    <div class="show">第一层组件显示的mesRef的值:{{ mesRef }}</div>
    <div class="show">第一层组件显示的mesReactive的值:{{ mesReactive }}</div>
    <div>
      <div>第一层组件引入第二层组件</div>
      <midassem></midassem>
    </div>
    <div class="changeMsg">
      <div class="change" @click="changeValue('one')">change message value</div>
      <div class="change" @click="changeValue('two')">change mesRef value</div>
      <div class="change" @click="changeValue('three')">change mesReactive value</div>
    </div>
  </div>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { provide } from 'vue';
import midassem from './assembly/midassem.vue';

let message = "来自第一层父组件的消息";
const mesRef = ref("来自第一层父组件的响应式消息");
const mesReactive = reactive({name: "alisa", time: "2024.3.15"});

let changeNum = 0;

// 使用provide在父组件中为后代组件提供数据
// 提供一个常量
provide('message', message);

// 提供一个响应式常量
provide('refmsg', mesRef);

// 提供一个reactive响应式对象
provide('reactivemsg', mesReactive);

/* 事件回调 */
const changeValue = (tag) => {
  changeNum++;
  if (tag === "one") {
    message = message + "-" + changeNum;
  }else if(tag === "two") {
    mesRef.value = mesRef.value + "-" + changeNum;
  }else if(tag === "three"){
    mesReactive.value = mesReactive.value + "-" + changeNum;
  }
}
</script>
<style scoped lang="less">
.box {
  display: flex;
  flex-direction: column;

  .show {
    background-color: rgb(109, 144, 166);
    margin: 20px;
    padding: 20px;
  }

  .changeMsg {
    display: flex;
    flex-direction: row;
    margin: 20px;
    padding: 20px;

    .change {
      background-color: rgb(215, 146, 102);
      font-size: 16px;
      padding: 20px;
      margin-right: 20px;
      width: 380px;
      text-align: center;
    }
  }
}
</style>

创建一个跟组件的子组件midassem,用于展示它的一个子组件lastassem,代码如下:

<template>
  <div class="box">
    <div>第二层组件,加载最后一层组件如下</div>
    <div>
      <lastassem></lastassem>
    </div>
  </div>
</template>
<script setup>
import lastassem from './lastassem.vue'
</script>
<style scoped>
.box {
  display: flex;
  flex-direction: column;
}
</style>

创建子组件lastassem,用于接收根组件provide的值,代码如下:

<template>
  <div class="box">
    <div>最深层组件获取的数据:</div>
    <div class="show">第一级组件的常量值:message = {{ message }}</div>
    <div class="show">第一层组件的ref响应式值: refMsg = {{ refMsg }}</div>
    <div class="show">第一层组件的reactive响应式对象:reactiveMsg = {{ reactiveMsg }}</div>
  </div>
</template>
<script setup>
import { inject } from 'vue';

// 接收第一层组件的常量值
const message = inject('message');

// 接收第一层组件的ref响应式值
const refMsg = inject('refmsg');

// 接收第一层组件的reactive响应式值
const reactiveMsg = inject('reactivemsg');

</script>
<style scoped lang="less">
.box {
  display: flex;
  flex-direction: column;

  .show {
    background-color: aquamarine;
    margin: 20px;
    padding: 20px;
  }
}

</style>

 看一下运行后的效果图(屏幕比较小把浏览器展示的图截成了两张):

点击下方的三个button,会分别改变根组件提供的那三个值。

青绿色的部分为子组件lastassem从根组件获取的值,值得注意的是:根组件中的ref与reactive类型的值发生改变时,子组件lastassem展示的在页面上的值也响应式的发生了改变

一些优化的技巧

        但如果你正在构建大型的应用,包含非常多的依赖提供,或者你正在编写提供给其他开发者使用的组件库,建议最好使用 Symbol 来作为注入名以避免潜在的冲突。

        我们通常推荐在一个单独的文件中导出这些注入名 Symbol,下面把上面的代码优化了一下,新建了一个symbols.js文件,专门用于存储symbol创建的key值:

/*
 如果你正在构建大型的应用,包含非常多的依赖提供,或者你正在编写提供给其他开发者使用的组件库,
建议最好使用 Symbol 来作为注入名以避免潜在的冲突。
*/
export const myAssemKey = Symbol();

   然后把根组件和lastassem组件的代码优化下,如下:

import { myAssemKey } from './utils/symbols.js';

const mesReactive = reactive({name: "alisa", time: "2024.3.15"});

// 通过Symbol作为key提供数据源
provide(myAssemKey, symbolMessage);
import { myAssemKey } from '../utils/symbols.js';

// 接收第一层组件使用symbol作为key值提供的数据源
const symbolMessage = inject(myAssemKey);

        下图为展示的新的图:


http://lihuaxi.xjx100.cn/news/2105716.html

相关文章

必看!波特五力模型带你洞悉市场全貌

波特五力模型是一种用于分析行业竞争力的框架&#xff0c;通过研究行业内部和外部的五个力量&#xff0c;帮助企业制定有效的战略和应对策略。本文将详细解析波特五力模型的各个方面&#xff0c;以及如何运用该模型来提升企业竞争力。 波特五力分析模型制作工具boardmix 一、什…

Kafka:分布式消息队列

1. 简介 介绍 Kafka 的概述、优势和劣势&#xff0c;以及应用场景。 2. 基本概念 2.1 架构 一个典型的 Kafka 体系架构包括若干 Producer、若干Broker、若干 Consumer&#xff0c;以及一个ZooKeeper集群。 ZooKeeper是Kafka用来负责集群元数据的管理、控制器的选举等操作的…

C语言例3-24:赋值表达式的例子

代码如下&#xff1a; #include<stdio.h> int main(void) {int i1,j;float f2.0f;// printf("fi-1 :%0.1f\n",fi-1); //ff(i-1)2.0// printf("ii>f :%d\n",ii>f); //i>f -->0 -->i0// printf("j!(i1) :%d\n",j…

算法沉淀——贪心算法二(leetcode真题剖析)

算法沉淀——贪心算法二 01.最长递增子序列02.递增的三元子序列03.最长连续递增序列04.买卖股票的最佳时机 01.最长递增子序列 题目链接&#xff1a;https://leetcode.cn/problems/longest-increasing-subsequence/ 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子…

数字人解决方案——ER-NeRF实时对话数字人论文解读

简介 本文提出了一种新的基于条件神经辐射场&#xff08;Condition NeRF&#xff09;的talking portrait合成框架ER-NeRF&#xff0c;能够在较小的参数量下实现高精度的实时渲染和快速收敛。该方法利用空间区域的不平等贡献来指导谈话肖像建模&#xff0c;以提高动态头部重建的…

Vmware虚拟机配置虚拟网卡

背景 今天同事咨询了我一个关于虚拟机的问题&#xff0c;关于内网用Vmware安装的虚拟机&#xff0c;无法通过本机访问虚拟上的Jenkins的服务。   验证多次后发现有如下几方面问题。 Jenkins程序包和JDK版本不兼容&#xff08;JDK1.8对应Jenkins不要超过2.357&#xff09;虚拟…

雾锁王国多人联机服务器搭建教程,免费创建!

免费自建雾锁王国Enshrouded服务器&#xff0c;先领取阿里云300元无门槛代金券&#xff0c;然后在雾锁王国Enshrouded专题页一键部署&#xff0c;不需要基础&#xff0c;鼠标点选即可10秒钟创建一台雾锁王国游戏服务器&#xff0c;超简单&#xff0c;阿里云服务器网aliyunfuwuq…

什么是Vector Database?

此为看完视频What is a Vector Database?后的笔记。 作者首先对数据库做了分类&#xff0c;其中RTweb表示real time web app。 然后对用例做了分类&#xff0c;最后一个就是适合于AI的近似搜索。 好处&#xff0c;包括灵活性&#xff0c;可扩展性和性价比。 本视频最重要的…