Vue3-23-组件-依赖注入的使用详解

什么是依赖注入

个人的理解 : 
    依赖注入,是在 一颗 组件树中,由 【前代组件】 给 【后代组件】 提供 属性值的  一种方式 ;
    这种方式 突破了 【父子组件】之间通过 props 的方式传值的限制,只要是 【前代组件】提供的 依赖,【后代组件】都可以执行注入使用;
    我愿称之为 【跨代传值】。

依赖注入使用到的 关键方法:
provide() : 提供依赖
inject() : 注入依赖

依赖注入使用的注意事项

1、依赖注入的组件 ,必须是 一棵组件树的 前后代关系,兄弟组件不支持;
2、不建议后代组件中直接修改 注入的依赖的值,建议 前代组件中 将修改依赖的方法一并暴露出去;
3、依赖注入支持 全局的注入(这个较为特殊一些);
借用官网的一张图就是下面的样子:

在这里插入图片描述

依赖注入的使用方式

1、注入普通值 : 直接指定 key  和 value 
2、注入响应式的值 : 注入的值是一个 响应式的对象
3、注入时提供默认值 :inject() 方法 第二个参数可以指定默认值,当没有提供依赖时 展示的时默认值
4、限制 提供的数据不能被 后代修改 : 使用 readonly 进行限制
5、同时提供响应式的修改方法
6、全局提供依赖 ; 可以在 app 中进行全局提供依赖,所有的组件都可以注入依赖
7、使用 Symbol() 的方式指定 key
8、给 依赖注入 提供 类型约束

下面对上述的清醒进行案例介绍:

1、注入普通值

provide(key,value) : 提供依赖
const value = inject(key) : 注入依赖

前代组件 : 提供依赖

<template>

    <div class="basediv">
      
        APP.vue 中的 msg : {{ msg }}

        <br><br>

        <!-- 引入子组件 -->
        <ChildComponent />
    
    </div>
  
</template>
    
<script setup lang="ts">

	// 引入 provide 方法
    import { ref,provide } from 'vue'

    // 引入子组件
    import ChildComponent from './ChildComponent.vue'

    // 声明父组件的一个变量
    const msg = ref('这是父组件的msg变量')

    // 提供一个普通的依赖对象
    provide('key1','key1 的值')

</script>
    
<style scoped>

    .basediv{
        width: 600px;
        height: 400px;
        border: 1px solid red;
    }
</style>

后代组件 : 注入依赖

<template>

    <!-- 子组件 -->
    <div class="childdiv">
        
        子组件 - msg : {{ msg }}
        <br>
        注入的普通的依赖值 :{{ key1Value }}
    </div>
    
</template>
    
<script setup lang="ts">

	// 引入 inject 方法
    import { ref,inject } from 'vue'

    // 声明一个变量
    const msg = ref('这是子组件的msg变量')

    // 注入依赖 - 普通的数据
    const key1Value = inject('key1')
    console.log('后代组件中接收到的 key1 的值 : ',key1Value)
    
</script>
    
<style scoped>

    .childdiv{
        width: 350px;
        border: 1px solid green;
    }

</style>

运行效果:

在这里插入图片描述

2、注入响应式的值

前代组件 : 提供依赖

<template>

    
    <div class="basediv">
      
        APP.vue 中的 msg : {{ msg }}

        <br>  
        APP.vue 中的 abc : {{ abc }}
        <br>
        <br>
        
        <!-- 引入子组件 -->
        <ChildComponent />
    
    </div>
    
  
</template>
    
<script setup lang="ts">

	// 引入 provide 方法
    import { ref,provide } from 'vue'

    // 引入子组件
    import ChildComponent from './ChildComponent.vue'


    // 声明父组件的一个变量
    const msg = ref('这是父组件的msg变量')

    // 提供一个响应式的依赖对象
    const abc = ref(1001)
    provide('key2',abc)

</script>
    
<style scoped>

    .basediv{
        width: 600px;
        height: 400px;
        border: 1px solid red;
    }
</style>

后代组件 : 注入依赖

<template>

    <!-- 子组件 -->
    <div class="childdiv">
        
        子组件 - msg : {{ msg }}
        <br>
        
        注入的响应式依赖 :{{ key2Value }}

    </div>
    
</template>
    
<script setup lang="ts">

	// 引入 inject 方法
    import { ref,inject} from 'vue'

    // 声明一个变量
    const msg = ref('这是子组件的msg变量')

    // 注入依赖-响应式的依赖
    const key2Value = inject('key2') 
    console.log('后代组件中接收到的 key2 的值 :',key2Value)
    
</script>
    
<style scoped>

    .childdiv{
        width: 350px;
        border: 1px solid green;
    }

</style>

运行效果:

在这里插入图片描述

3、注入依赖时写一个默认值

后代组件 在进行 依赖注入时,如果前代组件没有 提供依赖,则可以只用默认值进行代替
默认值 是 inject() 方法的第二个参数

前代组件 : 提供依赖

<template>

    <div class="basediv">
      
        APP.vue 中的 msg : {{ msg }}

        <br>  <br>

        <!-- 引入子组件 -->
        <ChildComponent />
    
    </div>
    
  
</template>
    
<script setup lang="ts">

	// 引入 provide 方法
    import { ref,provide } from 'vue'

    // 引入子组件
    import ChildComponent from './ChildComponent.vue'


    // 声明父组件的一个变量
    const msg = ref('这是父组件的msg变量')
    
</script>
    
<style scoped>

    .basediv{
        width: 600px;
        height: 400px;
        border: 1px solid red;
    }
</style>

后代组件 : 注入依赖

<template>

    <!-- 子组件 -->
    <div class="childdiv">
        
        子组件 - msg : {{ msg }}
        <br>
        
        注入的响应式依赖 :{{ key2Value }}

    </div>
    
</template>
    
<script setup lang="ts">

	// 引入 inject 方法
    import { ref,inject,toRef } from 'vue'

    // 声明一个变量
    const msg = ref('这是子组件的msg变量')

    // 注入依赖-响应式的依赖
    const key2Value = inject('key2','key2的默认值') 
    console.log('后代组件中接收到的 key2 的值 :',key2Value)

    
</script>
    
<style scoped>

    .childdiv{
        width: 350px;
        border: 1px solid green;
    }

</style>

运行效果:

在这里插入图片描述

4、提供响应式的修改方法

前代组件 : 提供依赖
此时提供的依赖是 一个对象的形式 :包含 数据方法

<template>

    <div class="basediv">
      
        APP.vue 中的 msg : {{ msg }}

        <br>  
        APP.vue 中的 abc : {{ abc }}
        <br>

        <!-- 引入子组件 -->
        <ChildComponent />
    
    </div>
    
</template>
    
<script setup lang="ts">

	// 引入 provide 方法
    import { ref,provide } from 'vue'

    // 引入子组件
    import ChildComponent from './ChildComponent.vue'


    // 声明父组件的一个变量
    const msg = ref('这是父组件的msg变量')

    // 提供一个响应式的依赖对象
    const abc = ref(1001)
    
    // 提供修改的方法
    const changeABC = ()=>{
        console.log('App 中修改 abc 的值为 888');
        abc.value = 888;
    }

    // 提供 依赖对象 和 方法
    provide('key2',{abc,changeABC})

</script>
    
<style scoped>

    .basediv{
        width: 600px;
        height: 400px;
        border: 1px solid red;
    }
</style>

后代组件 : 注入依赖

<template>

    <!-- 子组件 -->
    <div class="childdiv">
        
        子组件 - msg : {{ msg }}
        <br>
        注入的响应式依赖 :{{ key2Value }}
        <br>
        <button @click="changeAbcFromHd">修改 abc 的值</button>

    </div>
    
</template>
    
<script setup lang="ts">

	// 引入 inject 方法
    import { ref,inject} from 'vue'

    // 声明一个变量
    const msg = ref('这是子组件的msg变量')

    // 注入依赖-响应式的依赖
    const key2Value = inject('key2') 
    console.log('后代组件中接收到的 key2  :',key2Value)


    // 点击按钮修改 依赖的值
    const changeAbcFromHd = ()=>{
        key2Value.changeABC();
    }
    
</script>
    
<style scoped>

    .childdiv{
        width: 350px;
        border: 1px solid green;
    }

</style>

运行效果: 注意观察点击前后的 数据状态的变化

初始页面点击按钮后
在这里插入图片描述在这里插入图片描述

5、readonly 限制修改

当想限制传递的依赖只能是只读时,需要使用 readonly 关键字进行限制;
注意 : 只能是针对 没有提供修改函数的依赖,如果该依赖提供了修改函数,通过修改函数触发的修改仍然是有效的。

前代组件 : 提供依赖 : 一个普通的,一个只读的

<template>

    
    <div class="basediv">
      
        APP.vue 中的 msg : {{ msg }}

        <br>  
        APP.vue 中的 abc : {{ abc }}
        <br>
        APP.vue 中的 xyz : {{ xyz }}
        <br>

        <!-- 引入子组件 -->
        <ChildComponent />
    
    </div>
    
</template>
    
<script setup lang="ts">

	// 引入 provide 方法
    import { ref,provide,readonly } from 'vue'

    // 引入子组件
    import ChildComponent from './ChildComponent.vue'

    // 声明父组件的一个变量
    const msg = ref('这是父组件的msg变量')

    // 提供一个普通的依赖对象
    // provide('key1','key1 的值')
    // 提供一个响应式的依赖对象
    const abc = ref(1001)
    const xyz = ref(2002)
    

    // 提供 依赖对象
    provide('key2',abc)

    // 提供一个只读的依赖对象
    provide('key3',readonly(xyz))
    
    
</script>
    
<style scoped>

    .basediv{
        width: 600px;
        height: 400px;
        border: 1px solid red;
    }
</style>

后代组件 : 注入依赖

<template>

    <!-- 子组件 -->
    <div class="childdiv">
        
        子组件 - msg : {{ msg }}
        <br>
        <!-- 注入的普通的依赖值 :{{ key1Value }} -->
        <!-- <br> -->
        注入的响应式依赖key2 :{{ key2Value }}
        <br>
        注入的响应式依赖key3 :{{ key3Value }}
        <br>
    
    </div>
    
</template>
    
<script setup lang="ts">

	// 引入 inject 方法
    import { ref,inject } from 'vue'

    // 声明一个变量
    const msg = ref('这是子组件的msg变量')

    // 注入依赖-响应式的依赖
    const key2Value = inject('key2') 
    console.log('后代组件中接收到的 key2  :',key2Value)

    const key3Value = inject('key3') 
    console.log('后代组件中接收到的 key3  :',key2Value)

    // 延迟10s 执行修改
    console.log(new Date())
    setTimeout(() => {
        console.log(new Date(), '开始执行 依赖值的修改' )
        key2Value.value = 666;
        key3Value.value = 888;
    }, 10000);

</script>
    
<style scoped>

    .childdiv{
        width: 350px;
        border: 1px solid green;
    }

</style>

运行效果:

在这里插入图片描述
在这里插入图片描述

6、全局提供依赖

main.js : 提供全局依赖

import { createApp } from 'vue'

// 根组件
import App from './App.vue'

// 创建应用实例
const app = createApp(App)

// 直接注入一个全局的 依赖
app.provide('globalKey1','全局的变量值1')

// 挂在应用,渲染页面,这一步应该是在最后执行的
app.mount("#app")

后代组件 : 注入依赖

<template>
</template>
    
<script setup lang="ts">

	// 引入 inject 方法
    import { inject } from 'vue'

    const globalValue = inject('globalKey1')
    console.log('组件中注入全局的变量 :',globalValue)
    
</script>
    
<style scoped>
</style>

运行效果:

在这里插入图片描述

7、Symbol() 的方式指定 key

之前我们在提供依赖的时候,都是直接用字符串作为依赖的key,
说实话,这样做 一点毛病没有。
但是,大家不都是讲求规范嘛,Symbol() 就提供了这种方式:
1、写一个专门用来声明 key 的文件;
2、前代组件 引入 key,提供依赖;
3、后代组件 引入 key ,注入依赖。

key 文件


// 声明 两个key
export const KEY1 = Symbol()

export const KEY2 = Symbol()

前代组件 : 提供依赖

<template>

    <div class="basediv">
      
        APP.vue 中的 msg : {{ msg }}

        <br>  
        APP.vue 中的 abc : {{ abc }}
        <br>
    
        <!-- 引入子组件 -->
        <ChildComponent />
    
    </div>
    
  
</template>
    
<script setup lang="ts">

	// 引入 provide 方法
    import { ref,provide } from 'vue'

    // 引入子组件
    import ChildComponent from './ChildComponent.vue'

    // 声明父组件的一个变量
    const msg = ref('这是父组件的msg变量')

    // 引入定义的key
    import { KEY1 ,KEY2} from './key';
    // 提供依赖
    const abc = ref(1001)
    provide(KEY1,abc)
    provide(KEY2,'key2valueladfadfa')

</script>
    
<style scoped>

    .basediv{
        width: 600px;
        height: 400px;
        border: 1px solid red;
    }
</style>

后代组件 : 注入依赖

<template>

    <!-- 子组件 -->
    <div class="childdiv">
        
        子组件 - msg : {{ msg }}
        <br>
        <!-- 注入的普通的依赖值 :{{ key1Value }} -->
        <!-- <br> -->
        注入的响应式依赖key :{{ keyValue }}
        <br>
        注入的响应式依赖key2 :{{ key2Value }}
        <br>
      
    </div>
    
</template>
    
<script setup lang="ts">

	// 引入 inject 方法
    import { ref,inject } from 'vue'

    // 声明一个变量
    const msg = ref('这是子组件的msg变量')
    
    // 引入 key 
    import { KEY1,KEY2 } from './key';
    // 注入依赖
    const keyValue = inject(KEY1) 
    const key2Value = inject(KEY2) 

</script>
    
<style scoped>

    .childdiv{
        width: 350px;
        border: 1px solid green;
    }

</style>

运行效果:

在这里插入图片描述

8、 依赖注入 提供 类型约束

InjectionKey 接口 : 限制 依赖注入的值的类型

key文件


// 从 vue 中 导入 类型
import type { Ref,InjectionKey } from 'vue'

// 声明 key : 指定注入的依赖的值的类型是 Ref
export const KEY1 = Symbol() as InjectionKey<Ref<number>>
// 声明 key : 指定注入的依赖的值的类型是 string
export const KEY2 = Symbol() as InjectionKey<string>

前代组件 : 提供依赖

<template>

    <div class="basediv">
      
        APP.vue 中的 msg : {{ msg }}
        <br>  
        APP.vue 中的 abc : {{ abc }}
        <br>
    
        <!-- 引入子组件 -->
        <ChildComponent />
    
    </div>
  
</template>
    
<script setup lang="ts">

	// 引入 provide 方法
    import { ref,provide } from 'vue'

    // 引入子组件
    import ChildComponent from './ChildComponent.vue'

    // 声明父组件的一个变量
    const msg = ref('这是父组件的msg变量')
    
    // 引入定义的key
    import { KEY1 ,KEY2} from './key';
    // 提供依赖
    const abc = ref(1001)
    // 提供一个响应式的对象依赖
    provide(KEY1,abc) 
    // 提供一个 普通的 string 对象
    provide(KEY2,'key2valueladfadfa')

</script>
    
<style scoped>

    .basediv{
        width: 600px;
        height: 400px;
        border: 1px solid red;
    }
</style>

后代组件 : 注入依赖

<template>

    <!-- 子组件 -->
    <div class="childdiv">
        
        子组件 - msg : {{ msg }}
        <br>
        <!-- 注入的普通的依赖值 :{{ key1Value }} -->
        <!-- <br> -->
        注入的响应式依赖key :{{ keyValue }}
        <br>
        注入的响应式依赖key2 :{{ key2Value }}
        <br>
      
    </div>
    
</template>
    
<script setup lang="ts">

	// 引入 inject 方法
    import { ref,inject } from 'vue'

    // 引入 Ref 类型
    import type { Ref } from 'vue';

    // 声明一个变量
    const msg = ref('这是子组件的msg变量')

    // 引入 key 
    import { KEY1,KEY2 } from './key';
    // 注入依赖 : 同样可以使用泛型指定类型
    const keyValue = inject<Ref<number>>(KEY1) 
    const key2Value = inject<string>(KEY2,"默认值") 

</script>
    
<style scoped>

    .childdiv{
        width: 350px;
        border: 1px solid green;
    }

</style>

运行效果:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

至此,依赖注入的使用就完成了。

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

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

相关文章

「Qt Widget中文示例指南」如何创建一个计算器?(三)

Qt 是目前最先进、最完整的跨平台C开发工具。它不仅完全实现了一次编写&#xff0c;所有平台无差别运行&#xff0c;更提供了几乎所有开发过程中需要用到的工具。如今&#xff0c;Qt已被运用于超过70个行业、数千家企业&#xff0c;支持数百万设备及应用。 本文将展示如何使用…

【开源GIS】如何高效地学习GIS开源项目?一上来就读源码你就输了!

目录 &#x1f525;前言Step 1: 熟悉项目Step 2: Hello worldStep 3: 深入了解和使用Step 4: 可以看源码了&#xff01;Step 5: API 二次封装Step 6: 持续关注和学习 &#x1f525;前言 都知开源好&#xff0c;只看源码看不懂&#xff0c;是俺太菜了&#xff1f;no no no&#…

kubeadm方式重置k8s集群

以kubeadm方式部署的k8s&#xff0c;当出现问题&#xff0c;排查解决的难度会非常大&#xff0c;如果是实验环境&#xff0c;直接进行集群重置即可&#xff0c;如果是生产环境&#xff0c;如果集群已经崩掉了&#xff0c;而且短时间时间内无法定位原因的情况的下&#xff0c;建…

Ansible(一)

Ansible: 远程操作主机功能&#xff1a; 自动化运维&#xff08;playbook剧本YAML&#xff09; 是基于Python开发的配置管理应用部署攻具&#xff0c;在自动化运维当中&#xff0c;现在是异军突起 Ansible能批量配置&#xff0c;部署&#xff0c;管理上千台主机&#xff0c…

基于vite 初始化vue3项目并引入Vue Router和Ant Design Vue

基于vite 初始化vue3项目并引入常用的功能、组件。 Vue RouterAnt Design Vue 系列文章指路&#x1f449; 系列文章-基于Vue3创建前端项目并引入、配置常用的库和工具类 文章目录 创建ViteVue项目创建并运行WebStorm无法识别&#xff0c;需要在vite.config.js中定义alias 引入…

GNSS模块在野外探险中的应用

野外探险是一项令人兴奋的活动&#xff0c;而GNSS&#xff08;全球导航卫星系统&#xff09;模块的广泛应用为探险者提供了精准的导航、位置跟踪和安全保障。本文将深入探讨GNSS模块在野外探险中的应用&#xff0c;以及它如何改变和增强探险体验。 精准导航与路径规划&#xf…

基于SpringBoot的大病保险管理系统 JAVA简易版

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统配置维护2.2 系统参保管理2.3 大病保险管理2.4 大病登记管理2.5 保险审核管理 三、系统详细设计3.1 系统整体配置功能设计3.2 大病人员模块设计3.3 大病保险模块设计3.4 大病登记模块设计3.5 保险审核模块设计 四、…

VS Code配置Go语言开发环境

提示&#xff1a;首先这是一个新型语言&#xff0c;最好把vscode更新到最新版。 1&#xff1a;去官网下载Go语言编译器&#xff0c;之后配置到系统环境中&#xff0c;能看到版本就行。 2&#xff1a;创建一个文件夹&#xff0c;存放go的工具文件&#xff0c;我的在D:\GoFile\G…

职场如何与不同级别的领导打交道?学会3个小妙招吃遍天下

职场如何与不同级别的领导打交道&#xff1f;学会3个小妙招吃遍天下 简介 刚步入职场的时候&#xff0c;很多新人小白会患上权威恐惧症&#xff0c;简单来说就是害怕与领导打交道&#xff0c;职位越大的领导越害怕。有领导在的地方有多远就躲多远&#xff0c;更别说主动去找领…

嵌入式串口输入详细实例

学习目标 掌握串口初始化流程掌握串口输出单个字符掌握串口输出字符串掌握通过串口printf熟练掌握串口开发流程学习内容 需求 串口循环输出内容到PC机。 串口数据发送 添加Usart功能。 首先,选中Firmware,鼠标右键,点击Manage Project Items 接着,将gd32f4xx_usart.c添…

[PyTorch][chapter 8][李宏毅深度学习][Back propagation]

前言&#xff1a; 反向传播算法(英:Backpropagation algorithm&#xff0c;简称:BP算法)是一种监督学习算法&#xff0c;常被用来训练多层感知机。 它用于计算梯度计算中&#xff0c;降低误差。 目录&#xff1a; 链式法则 模型简介&#xff08;Model&#xff09; 损失函…

【YOLOv8量化】普通CPU上加速推理可达100+FPS

NNCF介绍 OpenVINO2023版本衍生出了一个新支持工具包NNCF(Neural Network Compression Framework – 神经网络压缩框架)&#xff0c;通过对OpenVINO IR格式模型的压缩与量化更好的提升模型在OpenVINO框架上部署的推理性能&#xff0c;github。 https://github.com/openvinoto…

银河麒麟v10 安装mysql 8.35

银河麒麟v10 安装mysql 8.35 1、下载Mysql安装包2、安装Mysql 8.352.1、安装依赖包2.2、安装Mysql2.3、安装后配置 1、下载Mysql安装包 访问官网下载链接 链接: https://dev.mysql.com/downloads/mysql/ 选择如下 点击下载按钮 下载安装包 2、安装Mysql 8.35 官方安装文档…

AWS Linux安装桌面并远程访问

文章目录 小结问题及解决参考 小结 在AWS Linux安装了桌面并进行远程访问。 问题及解决 需要使用过程桌面访问AWS Linux&#xff0c;这里在AWS服务器安装并使用Amazon Linux 2 MATE desktop。 检查OS版本&#xff1a; [ec2-userip-10-0-3-241 ~]$ grep PRETTY_NAME /etc/o…

算法设计与分析2023秋-头歌实验-实验七 动态规划

文章目录 第1关&#xff1a;数塔问题任务描述相关知识编程要求解题思路测试说明参考答案 第2关&#xff1a;最长公共子序列任务描述相关知识编程要求解题思路&#xff1a;测试说明参考答案 第3关&#xff1a;求序列-2 11 -4 13 -5 -2的最大子段和任务描述相关知识编程要求解题思…

可实现RSSD云硬盘120万IOPS的SPDK IO路径优化

一. 简介 用户对超高并发、超大规模计算等需求推动了存储硬件技术的不断发展&#xff0c;存储集群的性能越来越好&#xff0c;延时也越来越低&#xff0c;对整体IO路径的性能要求也越来越高。在云硬盘场景中&#xff0c;IO请求从生成到后端的存储集群再到返回之间的IO路径比较…

less基础介绍

什么是less&#xff1f; Less是一个C5S预处理器,Less文件后缀是,less。扩充了 CSS 语言,使CSS 具备一定的逻辑性、计算能力 注意事项&#xff1a; 浏览器不识别 Less 代码&#xff0c;目前阶段&#xff0c;网页要引入对应的 CSS 文件 VS Code 插件: Easy LESS&#xff0c;保存 …

JVM快速入门

JVM 字节码 字节码文件的组成 字节码由五个部分组成&#xff1a;基础信息 常量池 字段 方法 属性 基础信息&#xff1a; 魔数、字节码文件对应的版本号、访问标识&#xff08;public final&#xff09;、该类的父类索引、该类实现哪些接口的索引 魔数&#xff1a;文件无法…

鸿蒙 - arkTs:渲染(循环 - ForEach,判断 - if)

ForEach循环渲染&#xff1a; 参数&#xff1a; 要循环遍历的数组&#xff0c;Array类型遍历的回调方法&#xff0c;Function类型为每一项生成唯一标识符的方法&#xff0c;有默认生成方法&#xff0c;非必传 使用示例&#xff1a; interface Item {name: String,price: N…

ValueError: source code string cannot contain null bytes

解决&#xff1a;把存在这个问题的包&#xff0c;全部卸载重装 pip uninstall xxx pip install xxx