当前位置:网站首页 > 数据科学与大数据 > 正文

vue中组合式 API-依赖注入之provide和inject的用法(二)——添加响应性 & 污染全局数据、破坏了单向数据流,vuex可追踪数据 & 三种通信方式之父子通信、兄弟通信、跨级通信

vue中组合式 API-依赖注入之provide和inject的用法(二)——添加响应性 & 污染全局数据、破坏了单向数据流,vuex可追踪数据 & 三种通信方式之父子通信、兄弟通信、跨级通信

1、给 provide/inject 添加响应性

在vue3中给 provide/inject 添加响应性,使用 ref 或 reactive 。

//父组件代码 <template> <div> info:{ 
  {info}} <InjectCom ></InjectCom> </div> </template> <script> import InjectCom from "./InjectCom" import { provide,readonly,ref } from "vue" export default { setup(){ let info = ref("今天你学习了吗?") setTimeout(()=>{ info.value = "不找借口,立马学习" },2000) provide('info',info) return{ info } }, components:{ InjectCom } } </script> // InjectCom 子/孙组件代码 <template> { 
  {info}} </template> <script> import { inject } from "vue" export default { setup(){ const info = inject('info') setTimeout(()=>{ info.value = "更新" },2000) return{ info } } } </script> 

在订阅组件内修改值的时候,可以被正常修改,如果其他组件也使用该值的时候,状态容易造成混乱,所以需要在源头上规避问题。

readonly 只读函数,使用之前需要引入,如果给变量加上 readonly 属性,则该数据只能读取,无法改变,被修改时会发出警告,但不会改变值。

使用方法:

import { 
    readonly } from "vue" let info = readonly('只读info值') setTimout(()=>{ 
    info="更新info" //两秒后更新info的值 },2000) 
provide('info', readonly(info)) 
//发布 let info = ref("今天你学习了吗?") const changeInfo = (val)=>{ 
    info.value = val } provide('info',readonly(info)) provide('changeInfo',changeInfo) //订阅 const chang = inject('changeInfo') chang('冲向前端工程师') 

完整示例:

// 父组件代码 <template> <div> info:{ 
  {info}} <InjectCom ></InjectCom> </div> </template> <script> import InjectCom from "./InjectCom" import { provide,readonly,ref } from "vue" export default { setup(){ let info = ref("今天你学习了吗?") const changeInfo = (val)=>{ info.value = val } provide('info',readonly(info)) provide('changeInfo',changeInfo) return{ info } }, components:{ InjectCom } } </script> //InjectCom 子组件代码 <template> <div> <button @click="chang('冲向前端工程师')">更新值</button> </div> </template> <script> import { inject } from "vue" export default { setup(){ const info = inject('info') const chang = inject('changeInfo') return{ info, chang } } } </script> 
2、慎用 provide / inject

既然 provide/inject 如此好用,那么,为什么 Vue 官方还要推荐我们使用 Vuex,而不是用原生的 API 呢?

前面提到过,Vuex 和 provide/inject 最大的区别

Vuex 中的全局状态的每次修改是可以追踪回溯的,而 provide/inject 中变量的修改是无法控制的。换句话说,不知道是哪个组件修改了这个全局状态。

Vue 的设计理念借鉴了 React 中的单向数据流原则(虽然有 sync 这种破坏单向数据流的家伙),而 provide/inject 明显破坏了单向数据流原则。试想,如果有多个后代组件同时依赖于一个祖先组件提供的状态,那么只要有一个组件修改了该状态,那么所有组件都会受到影响。这一方面增加了耦合度,另一方面,使得数据变化不可控。如果在多人协作开发中,这将成为一个噩梦。

在这里,总结了使用 provide/inject 做全局状态管理的原则:

  • 多人协作时,做好作用域隔离;
  • 尽量使用一次性数据作为全局状态
使用 provide / inject 编写组件

使用 provide/inject 做组件开发,是 Vue 官方文档中提倡的一种做法。

以我们比较熟悉的 elementUI 来举例:

在 elementUI 中有 Button(按钮)组件,当在 Form(表单)组件中使用时,它的尺寸会同时受到外层的 FormItem 组件以及更外层的 Form 组件中的 size 属性的影响。

如果是常规方案,我们可以通过 props 从 Form 开始,一层层往下传递属性值。看起来只需要传递传递两层即可,还可以接受。但是,Form 的下一层组件不一定是 FormItem,FormItem 的下一层组件不一定是 Button,它们之间还可以嵌套其他组件,也就是说,层级关系不确定。如果使用 props,我们写的组件会出现强耦合的情况。

provide/inject 可以完美的解决这个问题,只需要向后代注入组件本身(上下文),后代组件中可以无视层级任意访问祖先组件中的状态。

部分源码如下:

export default { 
    name: 'ElButton', // 通过 inject 获取 elForm 以及 elFormItem 这两个组件 inject: { 
    elForm: { 
    default: '' }, elFormItem: { 
    default: '' } }, // ... computed: { 
    _elFormItemSize() { 
    return (this.elFormItem || { 
   }).elFormItemSize; }, buttonSize() { 
    return this.size || this._elFormItemSize || (this.$ELEMENT || { 
   }).size; }, //... }, // ... }; 
3、Vue中常见的组件通信方式可分为三类

1、父子通信

  • 父向子传递数据是通过 props,子向父是通过 events($emit);
  • 通过父链 / 子链也可以通信($parent / $children);
  • ref 也可以访问组件实例;
  • provide / inject;
  • a t t r s / attrs/ attrs/listeners;

2、兄弟通信

  • Bus;
  • Vuex;

3、跨级通信

  • Bus;
  • Vuex;
  • provide / inject
  • $attrs / $listeners
到此这篇vue中组合式 API-依赖注入之provide和inject的用法(二)——添加响应性 & 污染全局数据、破坏了单向数据流,vuex可追踪数据 & 三种通信方式之父子通信、兄弟通信、跨级通信的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • vue中组合式 API-依赖注入之provide和inject的用法(三)——实例之引用全局静态数据2024-12-02 23:36:09
  • axios请求本地json文件——调用路径只支持相对路径形式 & 设置、获取、清除sessionStorage & 跨组件通信之父组件有provide选项提供数据,子组件有inject选项来使用数据2024-12-02 23:36:09
  • vue中,el-table树形数据与懒加载——stripe斑马线 & row-key唯一标识id & lazy属性与加载函数load & default-expand-all之默认展开所有行2024-12-02 23:36:09
  • vue中,el-table树形数据与懒加载【实例】(一)——重置resetFields& lazy属性、hasChildren子项& el-select封装下拉组件& 获取当前登录人-reduce用法2024-12-02 23:36:09
  • vue中,el-table无数据(空数据)时,进行暂无数据的文本内容设置之具名插槽empty(v-slot=empty)和empty-text2024-12-02 23:36:09
  • vue中组合式 API-依赖注入之provide和inject的用法(一)——功能-把一个祖先组件指定的数据和方法,传递给其所有子孙后代 & provide-提供或发送数据, inject-接收数据2024-12-02 23:36:09
  • vue3中,引入data数据方式 & 引入组件的2种方式2024-12-02 23:36:09
  • 网络爬虫开发(一)-爬虫基础——基本介绍-爬虫是请求网站并提取数据的自动化程序、爬虫的基本工作流程 & 实例之发送http请求-爬取网址的网页信息2024-12-02 23:36:09
  • Baas接口标准(四)-留言板案例——实现服务端之数据查询、数据变更 & vue-apollovue实现客户端之整合apollo调用接口基本步骤、查询数据并模板填充、添加留言信息、格式化时间2024-12-02 23:36:09
  • vue3封装表单组件(二)02之el-tree-select组件的使用——懒加载、数据回显 & el-tree和el-select的结合体2024-12-02 23:36:09
  • 全屏图片