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

news2024/11/14 14:49:17

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.coloradmin.cn/o/2150759.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

powerbi -L10-文件夹内的文件名

powerbi -L10-文件夹内的文件名 Folder.Contents letSource Folder.Contents("\\your_folder\ your_folder "),#"Removed Other Columns" Table.SelectColumns(Source,{"Name", "Date modified", "Folder Path"}), in#&q…

国庆头像制作教程,这几种方法轻松制作国庆头像

随着国庆佳节的临近,朋友圈里是不是已经开始弥漫着浓浓的节日气氛?想要让你的头像也加入这场盛宴,成为最吸睛的存在吗?别急,今天就为你揭秘4款超实用的头像制作神器,能够让你的头像显现出浓郁的国庆节气氛&…

Qt 模型视图(二):模型类QAbstractItemModel

文章目录 Qt 模型视图(二):模型类QAbstractItemModel1.基本概念1.1.模型的基本结构1.2.模型索引1.3.行号和列号1.4.父项1.5.项的角色1.6.总结 Qt 模型视图(二):模型类QAbstractItemModel ​ 模型/视图结构是一种将数据存储和界面展示分离的编程方法。模…

高性能分布式搜索引擎Elasticsearch详解

♥️作者:小宋1021 🤵‍♂️个人主页:小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识,和大家一起努力呀!!! 🎈🎈加油! 加油&#xff01…

vue2 + moment 实现日历,并带有上个月和下个月日期的日历

在 Vue 2 中使用 moment 库绘制一个带有上个月和下个月日期的日历,可以通过以下步骤实现。这个日历将显示当前月份的天数,以及前一个月和下一个月的部分日期(通常为了让日历对齐为6行,每行7天)。 主要步骤&#xff1a…

外国药品位置检测系统源码分享

外国药品位置检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

C语言中值传递

C语言中&#xff0c;值传递的问题 #include <stdio.h> void modifyValue(int x) { x 10; // 修改的是x的副本&#xff0c;对原始数据无影响 printf("在函数中修改的结果是:%d\n",x); }int main() { int a 5; printf("Before: %d\n", a); modifyV…

【资料分析】刷题日记3

第一套 √ 考点&#xff1a;基期比重差很温柔的题 普通专科女生 占比 52.5% - 1.7% 50.8% 成人本专科女生 占比 57.8% - 4.6% 53.2% 相比降低了2.4% 知比重和部分量&#xff0c;求整体在花生老师的解法中体会啥叫适当约分 0.1899 / 47.8% / 87.5% 》0.19 / &#xff08;4…

碎纸片的自动拼接复原技术

摘要&#xff1a;破碎文件的拼接在司法物证复原、历史文献修复以及军事情报获取等领域都有着重要的应用。目前发现对碎纸片的拼接大部分由人工完成&#xff0c;准确率较高&#xff0c;但耗费大量人力财力及时间&#xff0c;效率很低。随着计算机技术的发展&#xff0c;人们试图…

机器人上的DPDK使用思考

引言 项目背景 人形机器人作为智能技术的集大成者&#xff0c;正逐步从科幻电影走进现实生活&#xff0c;广泛应用于工业制造、医疗健康、家庭服务等多个领域。在这一发展过程中&#xff0c;传感器技术的飞速发展和物联网技术的广泛应用&#xff0c;极大地提升了人形机器人对…

微服务实战:规则引擎Drools

1. 概述 * 规则引擎核心思想&#xff1a;将应用程序中的业务决策部分分离出来 * 使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效 2. 执行流程 drools规则引擎由以下三部分构成&#xff1a; Working Memory&#xff08;工作内存&#xff09; Ru…

360手机黑科技“位置穿越”功能修复 360位置穿越使用

​ 360手机刷机 360手机黑科技 360手机位置穿越 360手机位置修复 360手机站&#xff1a;360os.top 资源免费下载: os.360os.top 备用资源站&#xff1a;360手机-360手机刷机RootTwrp 360手机位置穿越 360手机位置穿越‌&#xff0c;是一款虚拟定位软件&#xff0c;无需进行r…

做谷歌外链有什么基础的要求?

做谷歌外链建设时有几个基本的要求需要注意。首先&#xff0c;收录率很关键&#xff0c;只有被谷歌成功收录的外链才会对网站产生正面影响。如果一个外链没有被收录&#xff0c;那它基本上对提升排名没有任何帮助 外链的多样性也是至关重要的。获取来自不同网站和平台的链接能为…

双token无感刷新

文章目录 &#x1f7e2;双token无感刷新1、token过期续期的五种方案对比2、双token的基本概念3、双token无感刷新的原理4、双token无感刷新的实现方式5.前端实现 ✒️总结 &#x1f7e2;双token无感刷新 对于token无感刷新这个东西有复杂度的话&#xff0c;它主要在后端&#x…

网站建设的服务器该如何选择?

服务器的选择对于网站的稳定运行、性能表现以及成本控制至关重要。以下是一些关键的考虑因素&#xff0c;帮助你选择适合的服务器&#xff1a; 明确需求&#xff1a;你需要先明确网站的需求和目标。这包括确定服务器将用于托管什么样的应用&#xff08;如Web前端、应用服务器、…

C/C++:优选算法(持续更新~~)

一、双指针 1.1移动零 链接&#xff1a;283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操…

【算法】BFS 系列之 多源 BFS

【ps】本篇有 4 道 leetcode OJ。 目录 一、算法简介 二、相关例题 1&#xff09;01 矩阵 .1- 题目解析 .2- 代码编写 2&#xff09;飞地的数量 .1- 题目解析 .2- 代码编写 3&#xff09;地图中的最高点 .1- 题目解析 .2- 代码编写 4&#xff09;地图分析 .1- 题…

103.运行tomcat的Tomcatstartup.bat时,终端打印的中文显示为乱码

目录 原因 解决方法 原因 当运行Tomcat的Tomcatstartup.bat时&#xff0c;如果终端中文显示为乱码&#xff0c;这通常是因为Tomcat使用的日志输出编码与Windows命令行默认的编码不匹配。 解决方法 针对这一问题&#xff0c;你可以尝试以下步骤来解决&#…

【Spring】IocDI详解(6)

本系列共涉及4个框架&#xff1a;Sping,SpringBoot,Spring MVC,Mybatis。 博客涉及框架的重要知识点&#xff0c;根据序号学习即可。 有什么不懂的都可以问我&#xff0c;看到消息会回复的&#xff0c;可能会不及时&#xff0c;请见谅&#xff01;&#xff01; 目录 本系列共…

深度图可视化显示(kitti)

文章目录 前言一、读取深度值与图像1、深度值读取2、图像读取 二、深度图可视化1、深度图可视化代码2、深度图可视化结果展示 三、深度图在图像上可视化1、可视化代码2、可视化坐标显示 四、完整代码 前言 kitti数据是一个通用数据&#xff0c;有关kitti的深度图像内容我已有博…