• 作者:老汪软件技巧
  • 发表时间:2024-09-29 11:01
  • 浏览量:

查找 provide 的数据:

数据的注入:

3. 详细源码分析

下面我们通过 Vue 的源码来进一步了解 provide 和 inject 的实现原理。

provide 的实现

在 Vue 中,provide 的逻辑实现很简单,主要是在组件实例化时,将 provide 的内容存储在组件实例的 _provided 属性中。

 // Vue 源码片段:初始化 provide
 export function initProvide(vm: Component) {
   const provide = vm.$options.provide;
   if (provide) {
     vm._provided = typeof provide === 'function'
       ? provide.call(vm) // 如果是函数,则执行该函数
       : provide;         // 否则直接将对象存储
   }
 }

inject 的实现

在组件初始化时,Vue 会调用 resolveInject 函数来处理 inject 的注入过程。

 // Vue 源码片段:解析 inject
 export function resolveInject(inject: any, vm: Component): ?Object {
   if (inject) {
     const result = Object.create(null);
     const keys = hasSymbol
       ? Reflect.ownKeys(inject)
       : Object.keys(inject);
 ​
     for (let i = 0; i < keys.length; i++) {
       const key = keys[i];
       const provideKey = inject[key].from;
       let source = vm;
       while (source) {
         if (source._provided && hasOwn(source._provided, provideKey)) {
           result[key] = source._provided[provideKey];
           break;
         }
         source = source.$parent;  // 向上查找父组件,直到找到注入的 provide
       }
     }
     return result;
   }
 }

resolveInject 的核心逻辑是:

遍历 inject 的 keys:获取需要注入的属性(可以是字符串数组或对象)。向上查找 provide:从当前组件的实例开始,逐级向上查找父组件的 _provided,直到找到包含 provide 数据的组件。注入数据:找到 provide 的数据后,将其注入到当前组件中。

如果没有找到对应的 provide 数据,Vue 并不会报错。也可以通过为 inject 提供默认值来避免数据未找到的情况。

4. 响应式处理

在 Vue 3 中,provide 和 inject 传递的默认数据不是响应式的。如果需要让提供的数据在后代组件中具备响应性,可以使用 Vue 3 的响应式 API,如 reactive 和 ref,让数据具备响应性。

响应式 provide 的示例

 import { reactive, provide, inject } from 'vue';
 ​
 // 父组件中提供响应式数据
 export default {
   setup() {
     const state = reactive({
       message: 'Hello from parent'
     });
 ​
     provide('state', state);
   }
 };
 ​
 // 子组件中注入响应式数据
 export default {
   setup() {
     const state = inject('state');
     return {
       state
     };
   }
 };

是的,Vue 官方确实建议将 provide 和 inject 主要用于高阶插件或组件库开发,而不建议在普通应用程序中广泛使用它们。这是因为 provide 和 inject 设计初衷和适用场景的特殊性,使得它更适合在特定情况下使用。以下是官方建议及原因:

5.为什么 provide 和 inject 不推荐用于普通应用程序代码

隐式依赖关系:

调试困难:

不利于维护:

有限的双向数据绑定支持:

6.为什么 provide 和 inject 适合高阶插件/组件库?

跨层级状态共享:

灵活性和可扩展性:

解耦合设计:

封装复杂逻辑:

适用场景对比特性普通应用程序代码高阶插件/组件库

数据流动

倾向于使用 props 和事件

倾向于共享全局状态、上下文

依赖管理

依赖显式的父子组件传递

依赖注入,跨层级传递更灵活

调试和可维护性

调试更直观

插件开发时避免逐级传递

可读性

父子关系明确,数据流清晰

解耦合设计,依赖更灵活

应用场景

普通组件间的通信

跨层级的数据共享、插件开发

何时使用 provide 和 inject?

适合使用的场景:

总结


上一条 查看详情 +没有了
下一条查看详情 +Vue 3.5 双向链表如何实现依赖收集