vue2中的provide與inject踩坑

背景

今天有一個(gè)孫組件需要部分?jǐn)?shù)據(jù)的情況,因?yàn)樽咏M件與父組件是之前同事已經(jīng)寫(xiě)好了的。我不想增加props改動(dòng)太多(實(shí)則就是偷懶),就想著用上之前官方不推薦使用的provideinject來(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)目中使用還是要注意。

有查看一下源碼,了解了一些provideinject的實(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ù)期。

其次是 還是不太推薦 使用provideinject,特別是當(dāng)前這個(gè)直接返回vue實(shí)例的行為。因?yàn)檫@個(gè)的能力實(shí)在有些太大了,很容易導(dǎo)致管理不當(dāng)?shù)幕靵y。比如在孫組件中直接this.app.xx = 123這個(gè)行為其實(shí)完全打亂了數(shù)據(jù)管理。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、組件間怎么傳值,具體說(shuō)說(shuō)代碼怎樣實(shí)現(xiàn) 子傳父:子向父是通過(guò) events($emit);通過(guò)父鏈 / 子鏈也可...
    如也_d1c0閱讀 838評(píng)論 0 1
  • **1、組件間怎么傳值,具體說(shuō)說(shuō)代碼怎樣實(shí)現(xiàn) ** 子傳父:子向父是通過(guò) events($emit);通過(guò)父鏈 /...
    北冥有魚(yú)_425c閱讀 480評(píng)論 2 7
  • 1、組件間怎么傳值,具體說(shuō)說(shuō)代碼怎樣實(shí)現(xiàn) 子傳父:子向父是通過(guò) events($emit);通過(guò)父鏈 / 子鏈也可...
    好名字都讓你們用了閱讀 1,777評(píng)論 0 34
  • 1、組件間怎么傳值,具體說(shuō)說(shuō)代碼怎樣實(shí)現(xiàn) 子傳父:子向父是通過(guò) events($emit);通過(guò)父鏈 / 子鏈也可...
    chang_遇見(jiàn)緣閱讀 4,087評(píng)論 12 87
  • 生命周期函數(shù)面試題 1.什么是Vue生命周期?vue生命周期是指vue是對(duì)象從創(chuàng)建到銷(xiāo)毀的過(guò)程。 2.Vue生命周...
    Angel_6c4e閱讀 17,085評(píng)論 2 51

友情鏈接更多精彩內(nèi)容