vue3.0源码解析之provide和inject

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

上文已经介绍了全局变量app.config.globalProperties的使用以及弊端,现在我们来讲解一下尤大提供的解决方案,provide和inject并分析下源码


提示:以下是本篇文章正文内容,下面案例可供参考

一、provide和inject的使用

provide可以向所有子孙组件提供数据以及提供修改数据的方法,子孙组件用inject使用数据。

案例:

  • 父组件
<script>
	 import { provide ,ref ,readonly} from "vue";
	    setup() {
	    //用ref包裹可使title变为响应式
	        let title=ref('title')
	        const updataTitle=()=>{
	           title.value='新title'
	        }
	        /*readonly包裹后可以在组件内引用时不被改变值。
	        否则在组件内可以直接通过title.value=***将值改变,
	        包裹后只能通过updataLocation()方法改变*/
	        provide('title',readonly(title))
	        provide('updataTitle',updataTitle)
	       }
</script>
  • 子组件
<script>
	import { inject } from "vue";
	    setup(){
	        const userTitle = inject('title')
	        const updataTitle= inject('updataTitle')
	        return{
	        	userTitle,updataTitle
	        }
	    }
</script>

二、源码分析

1. provide源码(vue3.14版本)

export function provide<T>(key: InjectionKey<T> | string | number, value: T) {
  if (!currentInstance) {
    if (__DEV__) {
    //Provide()只能在setup()中使用
      warn(`provide() can only be used inside setup().`)
    
    }
  } else {
    let provides = currentInstance.provides
	//默认情况下,实例继承父类的provides对象
	//但是当它需要提供自己的provide时,它使用父provide对象作为原型来创建自己的provide对象。。
	//在' inject '中,我们可以简单地从direct中查找注入父函数,让原型链做这些工作。
    const parentProvides =
      currentInstance.parent && currentInstance.parent.provides
    if (parentProvides === provides) {
      provides = currentInstance.provides = Object.create(parentProvides)
    }
    // TS不允许符号作为索引类型
    provides[key as string] = value
  }
}

2.inject核心代码

export function inject(
  key: InjectionKey<any> | string,
  defaultValue?: unknown,
  treatDefaultAsFactory = false
) {
  // 回退到' currentRenderingInstance '以便它可以被一个functional components调用
  const instance = currentInstance || currentRenderingInstance
  if (instance) {
    // #2400
    // 支持 `app.use`,
    // 如果实例是在根目录,回退到appContext的' provides '中
    const provides =
      instance.parent == null
        ? instance.vnode.appContext && instance.vnode.appContext.provides
        : instance.parent.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.call(instance.proxy)
        : defaultValue
    } else if (__DEV__) {
      warn(`injection "${String(key)}" not found.`)
    }
  } else if (__DEV__) {
    warn(`inject() can only be used inside setup() or functional components.`)
  }
}

总结

vvue3.0中可使用provide和inject替代app.config.globalProperties的使用

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木斯佳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值