最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 深究vue3中provide与inject

    正文概述 掘金(ZJSYNP)   2021-04-20   584

    在vue中,组件之间的通讯方式有很多种, 比如父组件向子组件传参使用props、子组件与父组件通信使用emit、兄弟组件通信使用eventBus/(provides/inject)。现在就一起来研究一下provide与inject的实现吧.

    provide

    在开发过程中, 我们经常会在父组件或更上级的组件中使用provide, 然后在子孙组件中使用inject来接受, vue中的provideAPI给我们的开发带来了很大的便利,而且在使用过程中, 父级组件不需要知道哪些子孙组件在调用当前的provide, 而子孙组件也不需要知道当前inject调用的函数来自哪里。 下面让我们一起来看一下vue3源码中关于provideAPI的实现吧。

    function provide<T>(key: InjectionKey<T> | string | number, value: T) {
      // 如果定义当前provide的组件不存在 在开发环境下发出警告⚠️
      if (!currentInstance) {
        if (__DEV__) {
          warn(`provide() can only be used inside setup().`)
        }
      } else {
        let provides = currentInstance.provides
        const parentProvides =
          currentInstance.parent && currentInstance.parent.provides
        if (parentProvides === provides) {
          provides = currentInstance.provides = Object.create(parentProvides)
        }
        // TS doesn't allow symbol as index type
        // 相同key值的情况下 父级组件的provide会覆盖根组件的provide
        provides[key as string] = value
      }
    }
    

    可以看到,相对与watchAPI来说 provide的代码并不是很长, 让我带大家一起分析一下吧. 从代码中可以看到 provide函数其实只做了一件事情, 就是将当前传入的函数添加到了provides对象中, 在其中需要注意的一点是, 当你在根组件传入一个provide之后, 如果key值相同,在父组件中传入的provide会覆盖根组件中的provide, 这点在开发过程中还是需要注意的. 接下来一起在看一下inject的实现吧.

    inject

    上面说到provideAPI方法将接受的所有key、value全部放到了一个provides对象中, 那么有些小伙伴应该可以猜到, inject函数其实是对provides中的方法进行了调用, 接下来就一起来看一下尤大的代码吧

    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 intance is at root
        const provides =
          instance.parent == null
            ? instance.vnode.appContext && instance.vnode.appContext.provides
            : instance.parent.provides
        // 判断当前的函数是否存在于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()
            : defaultValue
        } else if (__DEV__) {
          warn(`injection "${String(key)}" not found.`)
        }
      } else if (__DEV__) {
        warn(`inject() can only be used inside setup() or functional components.`)
      }
    }
    

    在inject函数中, 该函数接收三个参数, 第一个参数为你要调用的provide方法的key, 通过provides去调用当前的key值所对应的方法, 第二个参数为一个默认值, 第三个参数是一个选填的布尔值, 咱们接着往下分析,

    1. 代码中首先当前实例是否为根组件, 接着判断了provides中是否存在当前需要调用函数的key, 如果存在则返回这个函数的执行结果,
    2. 如果不存在则判断inject接收参数的数量, 这时候就要看第二个参数和第三个参数了, 第三个参数treatDefaultAsFactory更像是一个开关, 用来控制是否需要第二个参数,
    3. 如果treatDefaultAsFactory为true且第二个参数是个函数, 直接返回这个函数的默认结果, 否则会直接返回第二个参数.
    4. 如果不满足上述条件则会返回一段警告.

    怎么样,看完之后是不是觉得provide很简单呢?。


    起源地下载网 » 深究vue3中provide与inject

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元