背景
今天有一個(gè)孫組件需要部分?jǐn)?shù)據(jù)的情況,因?yàn)樽咏M件與父組件是之前同事已經(jīng)寫(xiě)好了的。我不想增加props改動(dòng)太多(實(shí)則就是偷懶),就想著用上之前官方不推薦使用的provide與inject來(lái)實(shí)現(xiàn)功能。誰(shuí)知道直接踩坑上,故記錄一下。
版本一
// 父組件
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
}
}
版本三 (正確的寫(xiě)法)
// 父組件
export default {
// ...
provide: function() (
return {
app: this
})
// ...
}
// 孫組件
export default {
inject: ['app'],
mounted() {
console.log(this.app)
}
}
原因
版本一 實(shí)在baidu到的里面無(wú)數(shù)人博客復(fù)制來(lái)的寫(xiě)法,但是我寫(xiě)的不對(duì)的原因是因?yàn)?例子們不是單文件組件的寫(xiě)法,只能說(shuō)僅供于學(xué)習(xí),實(shí)際項(xiàng)目中使用還是要注意。
有查看一下源碼,了解了一些provide與inject的實(shí)現(xiàn),從而得知了寫(xiě)法的問(wèn)題
源碼位置: 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執(zhí)行方法
: provide // 如果不是方法 則直接返回,嚴(yán)格模式下 this 為 undefined
}
}
// inject 的實(shí)現(xiàn)部分
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
}
}
代碼還是很簡(jiǎn)單的,可以參考 https://www.jb51.net/article/226645.htm 這個(gè)地址來(lái)查看一些參考
后記
很多東西還是要自己實(shí)際用一下才知道有什么問(wèn)題,當(dāng)然其實(shí)這個(gè)也只是因?yàn)橐恍?xiě)法上的問(wèn)題導(dǎo)致的結(jié)果不達(dá)預(yù)期。
其次是 還是不太推薦 使用provide與inject,特別是當(dāng)前這個(gè)直接返回vue實(shí)例的行為。因?yàn)檫@個(gè)的能力實(shí)在有些太大了,很容易導(dǎo)致管理不當(dāng)?shù)幕靵y。比如在孫組件中直接this.app.xx = 123這個(gè)行為其實(shí)完全打亂了數(shù)據(jù)管理。