vue3.0源码解析之provide和inject
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档provide和inject前言一、provide和inject的使用二、源码分析1. provide源码(vue3.14版本)2.inject核心代码总结前言上文已经介绍了全局变量app.config.globalProperties的使用以及弊端,现在我们来讲解一下尤大提供的解决方案,provide和inject并分析下源码提示:
·
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
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的使用
更多推荐
已为社区贡献6条内容
所有评论(0)