provide/inject源码实现

devtools/2025/3/18 8:15:11/

在 Vue 3 中,provide 和 inject 是通过 Vue 的响应式系统和组件实例机制实现的,底层是依赖 Vue 3 中的 Proxy 和 Reactive 来实现跨层级的数据传递和响应式绑定。以下是一个简化版的实现逻辑,帮助理解 Vue 3 中 provide 和 inject 是如何实现的。

  1. provide 的实现

provide 的核心目的是将数据存储在当前组件的上下文中,然后将这些数据传递给其后代组件。Vue 3 使用 Proxy 来实现对组件上下文的响应式管理。

基本的实现思路:

在父组件中,使用 provide 将数据存储到一个上下文对象中,父组件上下文数据存储在当前组件实例的 provides 对象中。

父组件的 provides 会暴露给子组件,子组件可以从父组件的上下文中读取提供的数据。

简化版的实现逻辑如下:

class Component {
constructor() {
this.provides = new Map(); // 存储提供的数据
}

provide(key, value) {
this.provides.set(key, value); // 设置提供的数据
}

inject(key) {
return this.provides.get(key); // 从当前组件的 provides 中获取
}
}

示例:

const parentComponent = new Component();
parentComponent.provide(‘user’, { name: ‘John’, age: 30 });

const childComponent = new Component();
const user = childComponent.inject(‘user’); // 获取父组件提供的数据
console.log(user); // 输出: { name: ‘John’, age: 30 }

  1. inject 的实现

inject 用来从当前组件的父组件(或祖先组件)中获取提供的数据。在实际实现中,Vue 会查找组件的父链(即组件树)来查找所需的 provide 数据。

基本的实现思路:

在子组件中,使用 inject 来获取上层组件通过 provide 提供的数据。Vue 会遍历组件树,查找最近的祖先组件。

如果当前组件没有提供数据,Vue 会继续向上查找直到根组件。

class Component {
constructor(parent = null) {
this.parent = parent;
this.provides = new Map(); // 存储提供的数据
}

provide(key, value) {
this.provides.set(key, value);
}

inject(key) {
// 从当前组件开始,逐级向父组件查找数据
let currentComponent = this;
while (currentComponent) {
if (currentComponent.provides.has(key)) {
return currentComponent.provides.get(key);
}
currentComponent = currentComponent.parent;
}
return undefined; // 如果找不到提供的数据,返回 undefined
}
}

示例:

// 父组件提供数据
const parentComponent = new Component();
parentComponent.provide(‘user’, { name: ‘John’, age: 30 });

// 子组件继承父组件
const childComponent = new Component(parentComponent);

// 孙组件继承子组件
const grandchildComponent = new Component(childComponent);

// 孙组件注入父组件提供的数据
const user = grandchildComponent.inject(‘user’);
console.log(user); // 输出: { name: ‘John’, age: 30 }

  1. 响应式机制

在 Vue 3 中,provide 和 inject 采用的是基于 Proxy 的响应式系统。Vue 3 的响应式系统使用 Proxy 来监听对象的变化,确保在数据变更时能够触发视图更新。

为了实现响应式传递,Vue 会通过 reactive 来包装提供的数据,然后使用 provide 提供的值会是一个响应式对象,子组件通过 inject 获取该对象时,数据的变化会自动反应到视图中。

简化的响应式实现:

function reactive(obj) {
return new Proxy(obj, {
get(target, prop) {
console.log(Accessing ${prop}); // 打印属性访问的日志
return target[prop];
},
set(target, prop, value) {
console.log(Setting ${prop} to ${value}); // 打印属性设置的日志
target[prop] = value;
return true;
}
});
}

class Component {
constructor(parent = null) {
this.parent = parent;
this.provides = new Map();
}

provide(key, value) {
this.provides.set(key, reactive(value)); // 提供响应式数据
}

inject(key) {
let currentComponent = this;
while (currentComponent) {
if (currentComponent.provides.has(key)) {
return currentComponent.provides.get(key); // 返回响应式数据
}
currentComponent = currentComponent.parent;
}
return undefined;
}
}

示例:

// 父组件提供响应式数据
const parentComponent = new Component();
const user = { name: ‘John’, age: 30 };
parentComponent.provide(‘user’, user);

// 子组件继承父组件
const childComponent = new Component(parentComponent);

// 孙组件继承子组件
const grandchildComponent = new Component(childComponent);

// 孙组件注入父组件提供的响应式数据
const injectedUser = grandchildComponent.inject(‘user’);
injectedUser.name = ‘Jane’; // 通过代理修改数据

console.log(user.name); // 输出: Jane,数据变化自动反映

总结

Vue 3 中的 provide 和 inject 实现是基于 Proxy 的响应式系统,组件的 provides 数据是响应式的,当数据变化时,依赖这些数据的组件会自动更新。provide 用来提供数据,inject 用来注入数据,支持跨组件层级的数据共享。通过 Proxy,Vue 3 能够实现跨层级数据传递和数据的自动更新,使得组件间的数据通信更加灵活和高效。


http://www.ppmy.cn/devtools/168025.html

相关文章

论文阅读:Deep Hybrid Camera Deblurring for Smartphone Cameras

今天介绍一篇 ACM SIGGRAPH 2024 的文章,关于手机影像中的去模糊的文章。 Deep Hybrid Camera Deblurring for Smartphone Cameras Abstract 手机摄像头尽管取得了显著的进步,但由于传感器和镜头较为紧凑,在低光环境下的成像仍存在困难&am…

【eNSP实战】基本ACL实现网络安全

拓扑图 要求: PC3不允许访问其他PC和Server1PC2允许访问Server1服务器,不允许其他PC访问各设备IP配置如图所示,这里不做展示 AR1接口vlan配置 vlan batch 10 20 30 # interface Vlanif10ip address 192.168.1.254 255.255.255.0 # inter…

C++ QT零基础教学(二)

一. 引子 在上一篇文章里面稍微讲解了一点C的基础,但是后面想了想要是还是继续单纯写C的内容的话要写到几百年年以后了,都不知道什么时候到QT了,所以这次就直接开始从QT开始描写了,当然肯定不会是很有难度,尽量还是会用…

Linux指令篇:jq

前言: 在 Linux 运维和开发过程中,我们经常需要处理 JSON 格式的数据,jq 是一个轻量级、功能强大的 JSON 解析工具,专门用于 查询、格式化、修改 JSON 数据。本文将介绍 jq 的安装、基本用法及实际案例,让你轻松掌握 j…

w260火锅店管理系统设计与实现

🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…

Node.js中SerialPort(串口)模块使用详解

Node.js中SerialPort(串口)模块使用详解 在现代物联网和嵌入式系统中,串口通信作为一种经典且高效的数据传输方式,依然扮演着重要角色。Node.js作为一款强大的JavaScript运行环境,通过SerialPort模块,为我们提供了一套简洁而强大…

大数据 Spark 技术简介

Apache Spark 是一种快速、通用、可扩展的大数据处理引擎,最初由加州大学伯克利分校开发。它提供了一种高效的数据处理框架,可以处理大规模数据集,并在分布式计算集群上进行并行处理。 Apache Spark 的基本概念包括以下几个要点:…

【机器学习chp12】半监督学习(自我训练+协同训练多视角学习+生成模型+半监督SVM+基于图的半监督算法+半监督聚类)

目录 一、半监督学习简介 1、半监督学习的定义和基本思想 2、归纳学习 和 直推学习 (1)归纳学习 (2)直推学习 3、半监督学习的作用与优势 4、半监督学习的关键假设 5、半监督学习的应用 6、半监督学习的常见方法 7、半…