vue2中的provide与inject踩坑
2022-04-25 本文已影响0人
这是一个无趣人
背景
今天有一个孙组件需要部分数据的情况,因为子组件与父组件是之前同事已经写好了的。我不想增加props改动太多(实则就是偷懒),就想着用上之前官方不推荐使用的provide
与inject
来实现功能。谁知道直接踩坑上,故记录一下。
版本一
// 父组件
export default {
// ...
provide: {
app: this
}
// ...
}
// 孙组件
export default {
inject: ['app'],
mounted() {
console.log(this.app) // undefined
}
}
版本二
// 父组件
export default {
// ...
provide: () => ({
app: this
})
// ...
}
// 孙组件
export default {
inject: ['app'],
mounted() {
console.log(this.app) // undefined
}
}
版本三 (正确的写法)
// 父组件
export default {
// ...
provide: function() (
return {
app: this
})
// ...
}
// 孙组件
export default {
inject: ['app'],
mounted() {
console.log(this.app)
}
}
原因
版本一 实在baidu到的里面无数人博客复制来的写法,但是我写的不对的原因是因为 例子们不是单文件组件的写法,只能说仅供于学习,实际项目中使用还是要注意。
有查看一下源码,了解了一些provide
与inject
的实现,从而得知了写法的问题
源码位置: vue\src\core\instance
// provide 部分
export function initProvide (vm: Component) {
const provide = vm.$options.provide
if (provide) {
vm._provided = typeof provide === 'function'
? provide.call(vm) // 如果是方法 则将自己 作为方法的this执行方法
: provide // 如果不是方法 则直接返回,严格模式下 this 为 undefined
}
}
// inject 的实现部分
export function resolveInject (inject: any, vm: Component): ?Object {
if (inject) {
// inject is :any because flow is not smart enough to figure out cached
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]
// #6574 in case the inject object is observed...
if (key === '__ob__') continue
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 // 自己未定义 则一直往上寻找
}
if (!source) {
if ('default' in inject[key]) {
const provideDefault = inject[key].default
result[key] = typeof provideDefault === 'function'
? provideDefault.call(vm)
: provideDefault
} else if (process.env.NODE_ENV !== 'production') {
warn(`Injection "${key}" not found`, vm)
}
}
}
return result
}
}
代码还是很简单的,可以参考 https://www.jb51.net/article/226645.htm 这个地址来查看一些参考
后记
很多东西还是要自己实际用一下才知道有什么问题,当然其实这个也只是因为一些写法上的问题导致的结果不达预期。
其次是 还是不太推荐 使用provide
与inject
,特别是当前这个直接返回vue实例的行为。因为这个的能力实在有些太大了,很容易导致管理不当的混乱。比如在孙组件中直接this.app.xx = 123
这个行为其实完全打乱了数据管理。