【Vue.js】provide & inject

前言:

前端项目的特点:

当前我们开发的前端项目都是以视图作为划分单位,将不同区域的视图显示划分成了许许多多的【碎片】。

组件化就是一种流行,高效,易维护的视图划分模式。

从组件化说起:

组件化 就是将视图划分成易维护 、可复用 、职责单一的视图碎片。

在项目中,这些碎片组成了我们项目需要的样子和功能,并最终组合成一个页面交互的整体(组件树)

在 Vue 组件的数据传递中,通常使用 props 这种标准化传递方式来进行数据传递。

模拟场景:

假定有一个这样的场景:

  1. 组件树上面有两个组件:组件 A、组件 B
  2. 组件 A 的可配置性很高,数据来源都是外界提供的
  3. 组件 B 的复用性很高,可以在任意组件之中渲染

从原则上来讲,组件 A 和组件 B 之间是可以相互依赖共用的。但是:

  1. 当组件树变得越来越复杂,它们需要嵌套和复用的次数越来越多(组合 & 嵌套),就会有可能产生许多层组件并未使用的数据出现的问题
  2. 当组件使用多次时,数据来源追踪困难
  3. 通常情况下,每次使用组件,都需要进行注册并且注册完成就要思考嵌套的数据来源

补充 - 组件设计的一些注意点:

  1. 组件依赖关系要简单
  2. 组件的嵌套不能太深(组件设计需要扁平化)

虽然 props 是组件数据传递的标准方式,但是上述的业务场景可能会导致标准的数据传递方式使用起来不太灵光!

这个时候,我们就需要使用 provide & inject (依赖注入) 的方式来解决我们在组件数据传递的标准方式不太使用的情景。

Provide & Inject

概述:

Provide & Inject是 Vue 官方提出的祖先组件派发数据给后代组件的非标准数据传递方式,具体步骤如下:

  1. 祖先组件使用 provide 提供数据(状态 & 方法)
  2. 后代组件调用 inject 接收组建组件传递的数据

代码示例:

基本使用

  1. 祖先定义
html 复制代码
<template>
  <Child />
</template>

<script>
  import { defineComponent } from 'vue';

  import Child from './Child.vue';
  
  export default defineComponent({
    name: 'Ancient',
    components: {
      Child
    },
    provide() {
      return {
        msg: 'hello my child'
      };
    }
  });
</script>
  1. 后代获取
html 复制代码
<template>
  <div>
    <h2>{{ msg }}</h2>
  </div>
</template>

<script>
  import { defineComponent } from 'vue';

  export default defineComponent({
    name: 'Child',
    inject: ['msg']
  });
</script>

补充:定义响应式数据

  • provide 和 inject 默认传递的数据不是响应式的 (不被代理 / 数据劫持)
  • 在 Vue3 中,如果在 options API 需要传递响应式数据,需要使用 Vue.computed 包裹数据!
  • 在 Vue2 中,只能传递响应式对象来维持数据的深度响应!

传递方法

  1. 祖先定义
html 复制代码
<template>
  <Child />
</template>

<script>
  import { defineComponent } from 'vue';

  import Child from './Child.vue';
  
  export default defineComponent({
    name: 'Ancient',
    components: {
      Child
    },
    provide() {
      const { print } = this;
      return {
        msg: 'hello my child',
        print
      };
    },
    methods: {
      print(msg) {
        console.log(msg);
        return this.print.bind(this);
      }
    },
  });
</script>
  1. 后代获取
html 复制代码
<template>
  <div>
    <h2 @click="print('hahaha')">{{ msg }}</h2>
  </div>
</template>

<script>
  import { defineComponent } from 'vue';

  export default defineComponent({
    name: 'Child',
    inject: ['msg', 'print']
  });
</script>

总结 - 什么场景下适合使用 Provide & Inject 呢?

  1. 在一个组件体系 下,如果有深度嵌套
  2. 在一个组件体系 下,多层级多个组件使用的时候
相关推荐
程序员初一12 小时前
我把跑了两年 WordPress 的机器重装了一遍,顺便把面板卸了
javascript
kyriewen12 小时前
别再用防抖做懒加载了:120 张图只加载出 4 张
前端·javascript·程序员
CodeMi14 小时前
2026 CSS 接管了这些 JS 的活:6 个 Baseline 特性的落地取舍
javascript·css
康小旺14 小时前
AI 写 Vue 总写成同一个味道:给它装 Skills,装的不是知识是边界
vue.js·typescript
全栈项目管理程序猿14 小时前
ArcGIS JS 基础教程(35):体元系列 - VoxelLayer 时间维度动画
前端·javascript
徐小夕16 小时前
JitKnow AI知识库 4.7 发布|多文档推理+拖拽 Agent + 技能库,打造更懂业务的 AI 知识中台
前端·vue.js·github
小poop16 小时前
从“雷峰塔”到“对象”:JavaScript基础语法入门指南
前端·javascript
chunyublog17 小时前
HDFS 上传文件名空格问题排障教程
前端·javascript·npm
FRing0318 小时前
JavaScript入门到精通二十九(内置构造函数(Object、Array))
开发语言·前端·javascript
天才熊猫君19 小时前
前端队列,我是怎么从 `push + shift` 换成游标的
前端·javascript