Provide/Inject 初始化

1. initInjections 依赖初始化

该步骤其实发生在 initState 之前,但是由于 provide/inject 一般是配合使用,所以这里调整了一下顺序。

该函数的定义与过程都比较简单:

export function initInjections(vm: Component) {
  const result = resolveInject(vm.$options.inject, vm)
  if (result) {
    toggleObserving(false)
    Object.keys(result).forEach(key => {
      if (__DEV__) {
        defineReactive(vm, key, result[key], () => warn(''))
      } else {
        defineReactive(vm, key, result[key])
      }
    })
    toggleObserving(true)
  }
}
export function resolveInject(inject: any, vm: Component): Record<string, any> | undefined | null {
  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]
      if (key === '__ob__') continue
      const provideKey = inject[key].from
      if (provideKey in vm._provided) {
        result[key] = vm._provided[provideKey]
      } else if ('default' in inject[key]) {
        const provideDefault = inject[key].default
        result[key] = isFunction(provideDefault) ? provideDefault.call(vm) : provideDefault
      } else if (__DEV__) {
        warn('')
      }
    }
    return result
  }
}
  • 在 initInjections 函数中,只是遍历了 options.inject 配置的依赖数据,并 关闭 了依赖数据的 响应式依赖收集,最后通过 defineReactive 将对应的数据挂载到实例 vm 上,以便后面能直接访问。

这就是官方提示的 为什么 provide/inject 的数据不是响应式的了。

  • 而 resolveInject 函数就是用来对组件的 inject 依赖数据进行处理,并返回一个没有多余原型链的对象。

在官方文档中,inject 接收一个字符串数组或者一个 key 为 string 的对象,而作为对象时则 必须 有 from 字段来表示依赖数据的获取指向,另外也接收一个 default 属性作为降级时使用的默认值。

但是,在 mergeOptions 之后,会将 options.inject 转为标准对象格式。

并且这里并没有对注入数据 provide[key] 进行处理,而是直接赋值;所以才有:如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

resolveInject() 函数就是解析标准格式 inject 配置,并将上层组件的 provide 的值或者 default 默认值绑定到函数返回对象中;如果这两个都没有,则会提示错误信息 “injection xx not found”

2. initProvide 注入数据初始化

初始化注入数据的过程也很简单,整个过程其实与 initInjection 类似。其函数定义如下:

export function initProvide(vm: Component) {
  const provideOption = vm.$options.provide
  if (provideOption) {
    const provided = isFunction(provideOption) ? provideOption.call(vm) : provideOption
    if (!isObject(provided)) {
      return
    }
    const source = resolveProvided(vm)
    
    const keys = hasSymbol ? Reflect.ownKeys(provided) : Object.keys(provided)
    for (let i = 0; i < keys.length; i  ) {
      const key = keys[i]
      Object.defineProperty(
        source,
        key,
        Object.getOwnPropertyDescriptor(provided, key)!
      )
    }
  }
}
export function resolveProvided(vm: Component): Record<string, any> {
  const existing = vm._provided
  const parentProvides = vm.$parent && vm.$parent._provided
  if (parentProvides === existing) {
    return (vm._provided = Object.create(parentProvides))
  } else {
    return existing
  }
}

官方文档中对 provide 配置项的说明是,可以是一个对象或者一个返回对象的函数。

  • 所以这里首先判断了 options.provide 的类型并获取到了结果,如果结果 不是对象则会直接退出。
  • 然后,则是初始化 provide 的数据。

此时会将当前实例的 provided 数据与父组件实例的 provided 进行比较,如果相同,则返回一个 以父组件实例 provided 数据为原型创建的对象,否则直接返回当前实例的 provided 数据。

因为每一个实例都会进行与父组件实例的注入数据比较,所以才能多层级传递

  • 最后,则是遍历 provided 对象,通过 Object.defineProperty 来处理数据获取。

总结

整个 provide/inject 的初始化过程都很清晰,只是通过少数校验和处理,将 provide 数据一层一层传递下去,直到 inject 依赖时读该改数据的值;

并且因为在初始化时会关闭响应式处理部分,所以 provide/inject 的 直接绑定数据 才不支持响应式;但

又因为 没有对数据的进行深层次处理,所以,原有的响应式数据才会继续触发整个响应式系统的改变。

以上就是Vue 2源码阅读 Provide Inject 依赖注入详解的详细内容,更多关于Vue Provide Inject 依赖注入的资料请关注Devmax其它相关文章!

Vue 2源码阅读 Provide Inject 依赖注入详解的更多相关文章

  1. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  2. vue自定义加载指令v-loading占位图指令v-showimg

    这篇文章主要为大家介绍了vue自定义加载指令和v-loading占位图指令v-showimg的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  3. vue使用动画实现滚动表格效果

    这篇文章主要为大家详细介绍了vue使用动画实现滚动表格效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  4. 关于Vue 监控数组的问题

    这篇文章主要介绍了Vue 监控数组的示例,主要包括Vue 是如何追踪数据发生变化,Vue 如何更新数组以及为什么有些数组的数据变更不能被 Vue 监测到,对vue监控数组知识是面试比较常见的问题,感兴趣的朋友一起看看吧

  5. Vue子组件props从父组件接收数据并存入data

    这篇文章主要介绍了Vue子组件props从父组件接收数据并存入data的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  6. Vue h函数的使用详解

    本文主要介绍了Vue h函数的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  7. VUE响应式原理的实现详解

    这篇文章主要为大家详细介绍了VUE响应式原理的实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

  8. vue+Element ui实现照片墙效果

    这篇文章主要为大家详细介绍了vue+Element ui实现照片墙效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. vue+elemet实现表格手动合并行列

    这篇文章主要为大家详细介绍了vue+elemet实现表格手动合并行列,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. iview+vue实现导入EXCEL预览功能

    这篇文章主要为大家详细介绍了iview+vue实现导入EXCEL预览功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部