Jinuss's blog Jinuss's blog
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

Web、WebGIS技术博客
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • reactivity响应式

  • runtime-core运行时核心模块

    • watch和watcherEffect源码解析
    • scheduler调度器
    • directive自定义指令实现原理
    • provide依赖和inject注入详解
      • 概览
      • 源码分析
        • provide
        • inject
    • 生命周期函数Lifecycle解析
    • 渲染器renderer源码解析
  • runtime-dom运行时DOM模块

  • 5.18源码学习》
  • runtime-core运行时核心模块
东流
2025-09-15
目录

provide依赖和inject注入详解

# 概览

vue3中提供了一种父子组件(也包括爷孙组件)的通信方式,即依赖provide和注入inject。父子组件固然可以通过属性以及emit实现数据交换,但是有一个弊端就是,只能逐层传递,而provide/inject只要是存在组件嵌套关系,父子关系的延续,就可以应用。

# 源码分析

provide和inject是是直接可以从vue3中导入使用的方法,实现文件路径:packages\runtime-core\src\apiInject.ts

# provide

provide方法就是往实例instance的provides属性中新增键值对。

provide的源码实现如下:

function provide(key, value) {
  if (!currentInstance) ; else {
    let provides = currentInstance.provides;
    const parentProvides = currentInstance.parent && currentInstance.parent.provides;
    if (parentProvides === provides) {
      provides = currentInstance.provides = Object.create(parentProvides);
    }
    provides[key] = value;
  }
}
1
2
3
4
5
6
7
8
9
10

provide方法接收键值对key,value;若是当前实例currentInstance不存在,则直接return;前面提到数据都是挂载到实例上。然后获取实例的provides,获取当前实例的父实例上的provides,然后判断parentProvides与provides是否相等,若相等,则说明二者都是null,然后通过Object.create创建一个纯净的对象;最后就是赋值。

在vue3的源码createComponentInstance即创建组件实例中,也是先判断parent.provides,若存在,则将父组件的provides赋值给当前实例的provides;若不存在则通过Object.create创建。

function createComponentInstance(vnode, parent, suspense){
  const appContext = (parent ? parent.appContext : vnode.appContext) || emptyAppContext;

  const instance = {
    provides: parent ? parent.provides : Object.create(appContext.provides),
  }
  return instance;
}
1
2
3
4
5
6
7
8

# inject

inject方法就是从provides中提供的数据获取key对应值,因为父子组件实例的provides是一条原型链,若父组件中不存在,则会继续查找父组件的父组件上是否存在。其实现如下:

function inject(key, defaultValue, treatDefaultAsFactory = false) {
  const instance = getCurrentInstance();
  if (instance || currentApp) {
    let provides = currentApp ? currentApp._context.provides : instance ? instance.parent == null || instance.ce ? instance.vnode.appContext && instance.vnode.appContext.provides : instance.parent.provides : void 0;
    if (provides && key in provides) {
      return provides[key];
    } else if (arguments.length > 1) {
      return treatDefaultAsFactory && shared.isFunction(defaultValue) ? defaultValue.call(instance && instance.proxy) : defaultValue;
    } else ;
  }
}
1
2
3
4
5
6
7
8
9
10
11

inject方法接收三个参数:key键/defaultValue默认值/treatDefaultAsFactory是否作为工厂函数。先是调用getCurrentInstance()获取当前的组件实例,然后判断组件实例或应用实例是否存在,若存在,则通过一些三元操作来获取provides,然后获取对应的值;若provides中不存在key属性,且参数超过1个,则判断默认值是否是函数以及是否是工厂模式,若是,则调用该函数,this为组件实例的代理对象;否则返回默认值。

编辑 (opens new window)
上次更新: 2025/09/15, 10:29:53
directive自定义指令实现原理
生命周期函数Lifecycle解析

← directive自定义指令实现原理 生命周期函数Lifecycle解析→

最近更新
01
createApp创建实例解析
09-15
02
渲染器renderer源码解析
09-15
03
生命周期函数Lifecycle解析
09-15
更多文章>
Theme by Vdoing | Copyright © 2024-2025 东流 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式