Vue 依赖注入组件通信:provide / inject 使用详解

image.png

引言

Vue.js 中,我们经常会遇到组件之间需要共享数据的情况。一种常见的解决方案是通过 props$emit 事件来进行数据传递,但对于多层嵌套的组件结构或共享状态的场景,这种方式显得繁琐而不直观。

幸运的是,Vue.js 提供了一个稍微优雅的解方案:依赖注入 - provideinject

provideinject是 Vue.js 2.2.0 版本引入的一对 API,它们为父组件所有子组件之间提供了一种特殊的通机制。通过在父组件使用provide提供数据,然后在子组件中使用inject引入,我们可以实现组件间的数据共享,避免了繁琐的 props 传递事件监听。

在本文,我们将深入研究provideinject的使用和注意事项,探讨它们在组件之间传递数据和状态共享中的应用场景,以及需要注意的一些细节。

一. 理解 provideinject

是什么?

provideinject是 Vue.js 2.2.0 版本引入的新特性,用于解决组件间跨层级通信的问题。它们的出现主要是为了弥补 props 和事件通信在层级较深的组件之间传递数据时的不便之处。

在传统的 props 和事件通信中,如果一个组件嵌套在多个层级的组件内部,需要将数据逐层通过 props 传递给子组件,或者通过触发事件来向父组件发送数据。这种方式在层级较深时会导致代码冗余,同时也增加了组件之间的耦合度。

为了简化跨层级组件间的通信,Vue.js 引入了provideinject通过在父组件中使用provide定义数据,并在子组件中使用inject进行注入,可以实现子组件直接获取父组件提供的数据,而不需要逐层传递 props 或触发事件。

provideinject的出现使得跨层级组件间的通信更加灵活和高效。它们适用于一些全局配置项、主题/样式传递以及跨层级组件通信等场景,可以有效地减少组件之间的耦合度,并提高代码的可维护性和复用性。

需要注意的是,provideinject并不是响应式的,也就是说当父组件中的数据发生变化时,子组件不会自动更新。因此,在使用provideinject时需要注意数据的更新问题,可以使用响应式的数据或计算属性来解决。

作用和优势

provideinject是 Vue.js 中用于跨组件层级通信的高级特性。它们的作用和优势如下:

作用:

  1. 跨层级数据传递provideinject允许在父组件中提供数据,并在子孙组件中进行注入,实现跨层级的数据传递,避免了通过 props 逐层传递数据的繁琐和冗余。

  2. 简化组件通信:通过将数据提供给整个组件树中的各个子组件,provideinject使得组件之间的通信更加直接和简洁。不需要逐层传递 props 或触发事件,子组件可以直接注入的数据中获取所需的信息。

  3. 全局配置和共享状态provideinject适用于一些全局配置项或共享状态的传递,比如应用程序的主题、用户身份认证信息等。这些数据可以被所有子组件共享和访问,避免了通过 propsVuex 来传递和管理全局数据的复性。

优势:

  1. 简化代码:相比较手动传递 props 或触发事件的方式,provideinject减少了组件间的耦合度,简化了代码逻辑,提高了代码的可读性和维护性。特别适用于层级较深的组件通信场景。

  2. 高效性能:由于数据直接注入到子组件中,provideinject的数据访问效率较高,减少了数据在组件树中的传递次数,有利于提升应用程序的性能。

  3. 灵活性provideinject提供了更灵活的数据传递方式,可以在父组件中动态提供数据,并在子组件中进行注入。这使得组件之间的关系更加松散,便于组件的重用和组合。

需要注意的是,provideinject并非适用于所有情况,它们应谨慎使用。在组件之间的通信模式选择上,需要考虑数据的层级关系、组件之间的耦合度以及数据的更新方式等因素。

实现原理

provideinject的实现原理涉及 Vue.js 底层的依赖注入系统。

Vue.js 中,依赖注入是一种设计模式,用于解决组件之间的依赖关系。Vue.js 的依赖注入实际上是通过"向上寻找"方式来实现的,即当一个组件需要使用某个依时,它会向上遍历父级组件,直到找一个提供了该依赖的组件。

具体来说,provideinject是基于 Vue.js 的响应式系统和虚拟 DOM 实现的。当一个组件使用provide提供数据时,Vue.js 会将该数据保存在当前组件的_provided属性中,同时将该数据转化为响应式数据。这样,当数据发生改变时,依赖于该数据的子组件也会自动更新。

当一个组件使用inject引入数据时,Vue.js 会从当前组件开始向上遍历父级组件,查找与provide提供的数据匹配的数据,并将其设置为当前组件的响应式数据。如果没有找到匹配的数据,inject的默认值将会生效需要注意的是,provideinject的绑定是在组件的创建阶段完成的,它并不会受到组树的动态变化影响。一旦提供和引入的发生改变,只有在组重新创建的情况下会生效。

总的来说,provideinject实现通过 Vue.js 底层依赖入系统,结合响应式系统和虚拟 DOM,实现了组件之间的数据共享和动更新。这为我们提供了一种便捷的方来解决多层嵌套组件之间的数据传递和状态管理问题

二. provide 如何使用

在组件中定义 provide

Vue.js 中,通过provide可以在父组件中定义要共享的数据或方法,以供子孙组件进行注入和使用。provide的使用方法如下:

  1. 在父组件中使用provide属性来定义要提供的数据或方法。provide是一个对象,其中以键值对的形式定义要提供的内容。例如:

    export default {provide: {message: "Hello, world!",foo() {console.log("This is method from the parent component.");},},// ...
    };
    

    上述例子中,父组件通过provide提供了一个名为message的字符串数据和一个名为foo的方法。

数据定义的不同方式

在 Vue.js 中,可以使用provide来提供数据给子组件,这样子组件可以通过inject来获取这些数据。provide提供数据的方式可以分为以下三种:静态值(String、Number)、动态(data、computed)和方法(函数)。

  1. 静态值(String、Number): 在provide选项中可以直接提供静态字符串或数字值。这些值对于所有的子组件来说是静态且不会随着时间的推移而改变的。例如:

    export default {provide: {message: "Hello, world!",count: 10,},// ...
    };
    

    在这例子中,通过provide选项提供了名为message的静态字符串值名为count的静态数值。

  2. 动态值(data、computed): 在provide选项中可以使用组件实例中的datacomputed属性来提供动态的数据。这些数据是响应式的,当它们发生变化时,被注入的子组件也将得到更新。例如:

    export default {data() {return {message: "Hello, world!",count: 10,};},computed: {countVal() {return this.count,}},provide() {return {message: this.message,count: this.countVal,};},// ...
    };
    

    在这个例子中,通过provide选项提供了messagecount两个动态值,这两个值是通过组件实例中的data属性和computed属性来提供的。

  3. 方法(函数) 在provide选项中可以提供一个方法,通过方法的调用来提供数据。方法可以接受参数并返回相应的值。例如:

    export default {data() {return {message: 'Hello, world!',count: 10}},methods: {getMessage() {return.message;},getCount() {return this.count;}},provide() {return {message: this.getMessage(),count: this.getCount()}},// ...
    }
    

    在这个例子中,通过provide选项提供了messagecount两个数据,这两个数据是通过调用组件实例中的方法来获取的。

通过这三种不同的方式,可以根据需要来提供静态的值、动态的值(data、computed)以方法(函数)。在子组件中可以通过inject选项来注入和使用这些提供的数据。

二. inject 如何使用

在组件中使用 inject

在 Vue.js 中,可以使用inject选项在组件中注入父组件通过provide提供的数据。通过在组件选项中定义inject来声明需要注入的数据,然后可以在组件中使用这些注入的数据。下面是关于inject的使用以及如何在组件中使用inject的说明:

  1. inject选项的使用: 在 Vue 组件中,可以使用inject选项来注入父组件通过provide提供的数据。inject可以是一个数组,也可以是一个对象。如果是数组,那么数组的元素就是要注入的数据的键名;如果是对象,那么对象的键名就是要注入的数据的键名,而键值可以是一个字符串,表示该数据的默认值。

    export default {inject: ["message", "count"],// ...
    };
    

    在这个例子中,inject选项是一个数组,它注入了名为messagecount的数据。

  2. 在组件中使用inject: 当注入的数据被声明为inject选项中的键名后,就可以在组件实例中使用这些数据。数据可以通过this访问。

    export default {inject: ["message", "count"],created() {console.log(this.message); // 输出 'Hello, world!'console.log(this.count); // 输出 10},// ...
    };
    

    在这个子中,通过this可以访问注入的messagecount`。

  3. 使用默认值: 组件中可以通过在inject选项中使用对象来设置注入数据的默认值。如果父组件提供相应的数据组件使用默认值。

  export {inject: {message: {default: 'Default message'},count: {default: 0}},created() {console.log(this.message);       // 输出 'Default message'console.log(this.count);         // 输出 0},// ...}

在这个例子中,如果父组件没有提供messagecount的数据,那么组件会使用指定的默认值。

总结来说,在组件中使用inject可以注入父组件通过provide提供的数据。可以通过数组或对象声明需要注入的数据,并在组件中使用这些注入的数据。如果没有提供相应的数据,可以设置默认值。通过inject,可以在组件中获取到父组件提供的数据,实现跨组件的数据传递和共享。

声明式注入和函数式注入

Vue.js 中,inject可以通过两种方式进行注入:声明式注入和函数式注入。

  1. 声明式注入

声明式注入是通过在组件选项中使用inject选项来声明需要注入的数据。inject可以是一个数组,数组的元素就是要注入的数据的键名。也可以是一个对象,对象的键名就是要注入的数据的键名,而键值可以是一个字符串,表示该数据的默认值。

export default {inject: ["message"],created() {console.log(this.message); // 输出 'Hello, world!'},// ...
};

通过在父组件的provide选项中提供了message数据,然后在子组件中使用inject选项声明了需要注入的message

  1. 函数式注入: 函数式注入是在组件中使用inject函数来手动注入数据。inject函数接收一个参数,就是要注入的数据的键名,然后返回对应的注入数据。

export default {created() {const message = this.$options.inject.message; // 手动注入 message 数据console.log(message); // 输出 'Hello, world!'},// ...
};

通过在子组件created钩子函数中使用inject函数来手动注入父组件提供的message数据。

小结

无论是声明式注入还是函数式注入,都可以实现父组件到子组件的数据注入。声明式注入更简洁,直接在组件选项中声明即可,而函数式注入则可以更加灵活地手控制注入的时机和方式,适用于特殊场景下的数据注入需求。

需要注意,在使用inject注入数据时,注入的数据是响应式的,当父组件提供的数据发生变化时,子组件也会相应地得到更新。但是,由于 Vue 的响应系统只能监听对象的属性的变化,而无法监听到对象本身的替换或重赋值,所以在使用inject注入的数据对象在父组件中发生整体替换时,子组件无法得更新。

数据和作用域

Vue.js 中,inject注入的数据可以是任意数据类型,包括基本类型、对象、数组和函数等。作用域方面,inject注入的数据具有以下几个特点:

  1. 数据类型inject注入的数据可以是任意合法的 JavaScript 数据类型,包括字符串、数字、布尔、对象、数组等。无论是基础类型还是复杂类型,都可以通过inject注入到组件中使用。

  2. 数据来源inject注入的数据是来自父组件通过provide提供的数据。父组件将数据通过provide选项提供,然后在子组件中使用inject选项声明需要注入的数据,以实现数据的传递和共享。

  3. 作用域inject注入的数据的作域是由父组件决定的。只有在父组件中provide选项提供的数据,子组件才通过inject选项来注入使用。也就是说,在父组件范围内声明的provideinject数据,可以在子组中访问和使用。而在其他件范围内提供的数据是无法通过inject注入使用的。

  4. 更新响应:当父组件中通过provide提供的数据发生变化时,子组件中通过inject注入的数据会相应地更新。这意味着,如果父组件中的提供的数据发生更新,那么在子组件中通过inject注的数据也会随之更新。

需要注意,虽然可以任意注入数据类型,但在使用时可能需要进行一些判断和类型转换操作,以确保数据正确使用。

综上所述,inject注入的数据可以是意数据类型,并且作用域是由父组件决定的,只有在父组件通过provide提供的数据才能在子组中通过inject注入使用。同时,当父组件提的数据发生变化时,通过inject 注入的数据也会相应的更新。

三. 应用场景

provideinject是在 Vue.js 中用于组件之间传递数据的一个机制,适用于以下场景:

  1. 跨层级组件通信

当组件层级比较深,需要在不同层级的组件之间进行数据传递时,可以使用provideinject。父组件通过provide提供数据,然后子组件通过inject注入使用。这样就可以避 props 层层传递或使用事件总线等方式进行通信。

  1. 全局配置项,公共数据或状态共享

当多个组件需要共享一些公共的数据或状态时,可以使用provide``inject来共享这些数据。在顶层组件中通过provide提数据,然后在任意子组件中通过inject注入使用。这样就可以方地共享数据,避免了数据在组件之的多次传递。

  1. 插件或第三方库集成

当需要将一些插件或三方库的功能封装到一个组件中,并让其他组件共享其功能时可以使用provideinject。通过在封装的组件中通过provide提供插件或库的实或方法,然后在其他组件中通过inject注入使用。这样可以让其他件方便地使用插件或库的功能,提高代码复用性。

需要注意provideinject并不适用于所有场景。在大部分情况下,推荐使用 props$emit 事件来进行组件之间的通信。provideinject的使用该谨慎,避免滥用,以确保代码的可读性和维护性。

四. 注意事项

在使用provideinject时,需要注意以下几点:

  1. 版本兼容性provideinject是 Vue.js 2.2.0 版本引入的特性,所以在使用前需要确保 Vue 的版本在 2.2.0 及以上。

  2. 依赖关系provideinject是依赖于组件关系的。只有在要共享数据组件的父级组件使用provide,并且在要使用这些数据的子组中使用inject,能建立起正确的依赖关系。

  3. 命名冲突:多个组件使用相的键名进行``时,后面提供的数据会覆盖前面提供的数据。在使用时需要确保键名的唯性,以避免命冲突。

  4. 对象引用:在使用provide时,提供任意类型的数据,包括对象。当提供的数据对象时,子组件使用时会继承父组件所提供对象引用。这意味着,如果在子组件中修改了该对象中的属性或方法,也会影响到父组件中的相应对象。

  5. 不适合响应式:尽管可以提供对象类型的数据,但是不推荐提供响应式的数据。因为在子组件中使用 inject接收到的数据不会保持响应式,子组件无法侦听其变化。如果需要响应式数据,可以考虑使用 Vue 的状态管理工具(Vuex)或其他全状态管理方法。

    不适合响应式是 Vue.js 框架刻意为之的,Vue的官方是这么说的,如下图所示

image.png

  1. 限制注意事项:如开发者指南所述,在 Vue 3 及以上版本中,provideinject有一些限制,包括在 Setup 函数无法使用provideinject。因此,在使用时注意检查版本以及相关文档的说明。

正确认识和合理运用以上注意事项将帮助我们更好地使用provideinject,从实现组件间的数据传递和共享。

结语

在本文中,我们详细讲解了 Vue.js 中的provideinject的使用和注意事项。

通过provideinject,我们可以实现组件之间的数据共享,避免了繁琐的 props 传递和事件监听。这使得我们可以更轻松地在组件树中传递数据,提高了代码的可维护性和可读性。

但需要注意的是,provideinject要谨慎使用。在使用时,需要注意版本兼容性、依赖关系、命名冲突、对象引用和不适合响应式的情况。同时,在 Vue 3 及以上版本中,provideinject有一些限制需要注意。

希望本文对你理解和运用provideinject有所助。通过合理地使用这特性,你可以更好地织和管理组件之间数据传递,提升开发效率。

参考资料

依赖注入 - Vue 2 官方文档

依赖注入 - Vue 3 官方文档

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

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

相关文章

web渗透—RCE

一:代码执行 相关函数 1、eval()函数 assert()函数 (1)原理:将用户提交或者传递的字符串当作php代码执行 (2)passby:单引号绕过:闭合注释;开启GPC的话就无法绕过(GPC就是将单引号转换为"反斜杠单引号"&a…

希亦超声波清洗机值得购买吗?百元清洁技术之王,大揭秘!

现代社会的高速发展,很多人由于工作繁忙的原因,根本没有时间去清洗自己的日常物品,要知道这些日常物品堆积灰尘之后是很容易就滋生细菌的,并且还会对人体的健康造成一定的危害!这个时候很多人就会选择购买一台超声波清…

什么是CSRF攻击,该如何防护CSRF攻击

CSRF攻击(跨站请求伪造,Cross-Site Request Forgery)是一种网络攻击手段,攻击者利用已通过身份验证的用户,诱导他们在不知情的情况下执行未授权操作。这种攻击通常发生在用户登录到可信网站并且有活动的会话时&#xf…

Python编码系列—Python组合模式:构建灵活的对象组合

🌟🌟 欢迎来到我的技术小筑,一个专为技术探索者打造的交流空间。在这里,我们不仅分享代码的智慧,还探讨技术的深度与广度。无论您是资深开发者还是技术新手,这里都有一片属于您的天空。让我们在知识的海洋中…

cv2.bitwise_or 提取ROI区域

原图如下所示,想提取圆形ROI区域,红色框 img np.ones(ori_img.shape, dtype"uint8") img img * 255 cv2.circle(img, (50,50), 50, 0, -1) self.bitwiseOr cv2.bitwise_or(ori_img, circle)使用一个和原图尺寸一致的图像做mask,图白圆黑 以…

MySQL:索引02——使用索引

目录 引言 1、自动创建索引 2、手动创建索引 2.1 主键索引 2.2 查看索引信息 2.3 唯一索引 2.4 普通索引 2.5 复合索引 3、删除索引 3.1 主键索引 3.2 其他索引 4、查看执行计划 4.1 不加条件,查询所有 4.2 使用主键查询 4.3 子查询使用索引 4.4 普通索…

【架构设计】多级缓存:应用案例与问题解决策略

【架构设计】多级缓存:应用案例与问题解决策略 多级缓存系统的工作原理及其在提升应用性能方面的关键作用。通过对比本地缓存与分布式缓存的特点 | 原创作者/编辑:凯哥Java | 分类:架构设计系列教程 多级缓存…

在基准测试和规划测试中选Flat还是Ramp-up?

Flat测试和Ramp-up测试是各有优势的,下面我们就通过介绍几种实用的性能测试策略来分析这两种加压策略的着重方向。 基准测试 基准测试是一种测量和评估软件性能指标的活动,通过基准测试建立一个已知的性能水平(称为基准线)&…

WPS生成目录

导航窗格:视图->导航窗格 可修改标题的样式,之后的标题直接套用即可 修改其他标题样式也是这样 添加编号:可以选上面的模版 也可自定义编号 生成目录:引用->目录->选用一个 但是我想把目录插到另一页 当我添加几个标题…

Spark-RDD持久化

一、Spark的三种持久化机制 1、cache 它是persist的一种简化方式,作用是将RDD缓存到内存中,以便后续快速访问,提高计算效率。cache操作是懒执行的,即执行action算子时才会触发。 2、persist 它提供了不同的存储级别&#xff0…

无人机黑飞打击技术详解

随着无人机技术的普及,无人机“黑飞”(未经授权或违反规定的飞行)现象日益严重,对公共安全、隐私保护及重要设施安全构成了严重威胁。为有效应对这一挑战,各国政府和安全机构纷纷研发并部署了一系列无人机黑飞打击技术…

HTML简介

HTML简介 1.HTML概述2.HTML元素3.HTML属性4.HTML 注释5.HTML颜色 1.HTML概述 HTML 是用来描述网页的一种语言。 HTML 指的是超文本标记语言HTML 不是一种编程语言&#xff0c;而是一种标记语言标记语言是一套标记标签HTML 使用标记标签来描述网页 例子&#xff1a; <htm…

Kotlin cancel CoroutineScope.launch的任务后仍运行

Kotlin cancel CoroutineScope.launch的任务后仍运行 import kotlinx.coroutines.*fun main() {runBlocking {val coroutineScope CoroutineScope(Dispatchers.IO)val job coroutineScope.launch {var i 0while (i < Int.MAX_VALUE) {iprintln(i)}}// 2ms 取消协程delay(…

2.计算机网络基础

2. 计算机网络基础 (1) 计算机网络的定义 计算机网络是指将地理位置不同、具有独立功能的多个计算机系统通过通信线路和设备连接起来,以功能完善的网络软件实现网络中资源共享的系统。最简单的定义是:计算机网络是一些互相连接的、自治的计算机系统的集合。最庞大的计算机网…

在 PostGIS 中进行千万级空间数据的空间查询和关键字查询

一、目的 本测试在探究在有限的计算机配置下&#xff0c;如何高效地对千万级的空间数据进行空间查询和关键字查询。通过实际操作和测试&#xff0c;评估不同查询策略的性能&#xff0c;为处理大规模空间数据提供可行的解决方案。 计算机配置如下&#xff1a; 内存&#xff0…

声网SDK脚本运行错误

文章目录 运行步骤无法运行.bat电脑出现警告--更改执行策略若无出现-更新power shell搜索最新版本的 PowerShell安装新版本 仍无法解决-手动下载第三方库 2024-9-9运行步骤 无法运行.bat 电脑出现警告–更改执行策略 若无出现-更新power shell 搜索最新版本的 PowerShell 在…

记录|如何对批量型的pictureBox组件进行批量Image设置

目录 前言一、问题表述二、批量化处理更新时间 前言 参考文章&#xff1a; 一、问题表述 问题就是上图所示&#xff0c;这些的命名风格统一&#xff0c;只是最后的数字是不同的。所以存在可以批量化进行处理的可能性。 二、批量化处理 private void SetPictureBoxImages(){for…

ElementPlus表单验证报错 formEl.validate is not a function

出现问题的代码 <!-- 密码重置弹框 --><el-dialog v-model"innerVisible" width"500" title"密码重置" append-to-body><el-form ref"ruleFormRef" style"max-width: 600px" :model"passForm" sta…

HarmonyOS元服务与卡片

元服务与卡片 文章目录 一、元服务1.介绍2.常见元服务项目步骤 二、卡片1.介绍2.卡片的创建3.卡片的数据的变更4.卡片的进程间通讯4.1使用工具包4.2使用步骤 5.卡片路由postCardAction&#xff1a;快速拉起后台5.1格式5.2快速拉起指定页面--router5.3调用后台功能--call5.3卡片…

委托的注册和注销

让我们来回顾一下委托的内容。 委托 是一种复杂的数据类型&#xff0c;需要我们先定义出来。当定义好类型后&#xff0c;声明委托变量来使用。 可以装载方法&#xff0c;只可以装载具有相同返回类型和参数列表的方法。 委托变量名&#xff08;参数列表&#xff09;&#xf…