惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
Vercel News
Vercel News
F
Fortinet All Blogs
月光博客
月光博客
G
Google Developers Blog
博客园 - Franky
GbyAI
GbyAI
The Cloudflare Blog
I
InfoQ
雷峰网
雷峰网
WordPress大学
WordPress大学
罗磊的独立博客
大猫的无限游戏
大猫的无限游戏
T
The Blog of Author Tim Ferriss
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 聂微东
小众软件
小众软件
腾讯CDC
B
Blog
量子位
V
V2EX
S
SegmentFault 最新的问题
Google DeepMind News
Google DeepMind News

时间的朋友

Windows 命令行密码重置 Anaconda安装 typescript 注解解读1 Konvajs Shape加载自定义图片 sshpass 使用 why-is-node-running webgl笔记 SharedArrayBuffer is not defined blender 常用快捷键 | 时间的朋友 vue -- v3.4commit提交记录2 vue2 升级vue3报错问题整理 着色器 expressjs 源码 hyper-V arch linux 网络配置 element input数字格式化 three 拼接货架 WebAudio笔记 Windows nginx重启bat脚本 vue -- v3.4commit提交记录 URI malformed vue3 -- Class 对象在组件中使用范例 | 时间的朋友 ruby 安装和升级 element-plus 老版本cascader使用卡死问题 vue3 内置Transition组件 | 时间的朋友 前端memo的实现 | 时间的朋友 Vue -- vue-class-component源码 | 时间的朋友 linux 优化脚本 typescript 装饰器 | 时间的朋友 microbundle 源码 | 时间的朋友 WSL2问题解决WslRegisterDistribution failed with error: 0x800701bc
vue -- provide和inject原理 | 时间的朋友
2023-03-08 · via 时间的朋友

Published: · LastMod: March 09, 2023 · 685 words

Vue3 provide和inject原理 🔗

packages/runtime-core/src/apiInject.ts

“version”: “3.3.0”

provideinject是用于组件间传递数据使用,在顶层组件使用provide,子组件使用inject获取值

provide 🔗

provide 传入2个参数

  • 第一个参数是key值,可以是字符串或者symbol类型
  • 第二个参数是需要向下传递的值
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
export function provide<T>(key: InjectionKey<T> | string | number, value: T) {
    let provides = currentInstance.provides
    // by default an instance inherits its parent's provides object
    // but when it needs to provide values of its own, it creates its
    // own provides object using parent provides object as prototype.
    // this way in `inject` we can simply look up injections from direct
    // parent and let the prototype chain do the work.
    // 默认情况下,实例继承其父对象的提供对象
    // 但是当它需要提供自己的价值时,它会创造自己的价值
    // 自己提供对象使用父提供对象作为原型。
    // 这样在 `inject` 中我们可以简单地从直接父级查找注入并让原型链完成工作。
    const parentProvides =
      currentInstance.parent && currentInstance.parent.provides
    if (parentProvides === provides) {
      provides = currentInstance.provides = Object.create(parentProvides)
    }
    // TS doesn't allow symbol as index type
    provides[key as string] = value
}

这里有个点,当它需要提供自身的值时,把provides保存到当前组件上和当前组件的父组件上

inject 🔗

根据key值获取provide中提供的值

  • 参数1: 和provide中相互匹配的key值
  • 参数2: 默认值(如果provide提供了值,则输出provide中的值,否则输出默认值)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
export function inject(
  key: InjectionKey<any> | string,
  defaultValue?: unknown,
  treatDefaultAsFactory = false
) {
  // fallback to `currentRenderingInstance` so that this can be called in
  // a functional component
  const instance = currentInstance || currentRenderingInstance
  if (instance) {
    // #2400
    // to support `app.use` plugins,
    // fallback to appContext's `provides` if the instance is at root
    const provides =
      instance.parent == null
        ? instance.vnode.appContext && instance.vnode.appContext.provides
        : instance.parent.provides

    if (provides && (key as string | symbol) in provides) {
      // TS doesn't allow symbol as index type
      return provides[key as string]
    } else if (arguments.length > 1) {
      return treatDefaultAsFactory && isFunction(defaultValue)
        ? defaultValue.call(instance.proxy)
        : defaultValue
    } else if (__DEV__) {
      warn(`injection "${String(key)}" not found.`)
    }
  } else if (__DEV__) {
    warn(`inject() can only be used inside setup() or functional components.`)
  }
}