Vue provide/inject使用

想象一個(gè)場(chǎng)景,子組件依賴父組件傳遞的props,如果有多個(gè)這樣的props,其實(shí)已經(jīng)很煩了,當(dāng)有多個(gè)子組件,或者孫組件也依賴于由上至下的props時(shí),寫那么多props簡(jiǎn)直是要了親命了。

為了解決這種麻煩,產(chǎn)生了vuex。但是我們肯定希望組件的高可復(fù)用性,不引入vuex就能實(shí)現(xiàn)功能,那就要考慮vue本身是否支持這種能力了。熟悉React開發(fā)的人應(yīng)該會(huì)想到Context這個(gè)高階組件,它通過ProviderConsumer,可以使得無限嵌套的父子組件共有一個(gè)數(shù)據(jù)源。Vue也有一個(gè)類似的,連名字都很相似,就是這篇文章的主人公provideinject。

依賴注入 ,官網(wǎng)有個(gè)例子,講述了為何我們需要 provide,它是可以終結(jié)復(fù)雜數(shù)據(jù)嵌套的神器。慣例先吹一波,不然寫這篇文章的意義沒了,=^^= 。閑話少說,上代碼。

// parent組件
<template>
  <div>
    <div>{{test}}</div>
    <button @click="changeTest">修改test的值</button>
    <son></son>
  </div>
</template>

<script>
import Son from "./Son";
export default {
  name: "parent",
  components: { Son },
  provide() {
    return {
      injectData: this.test
    };
  },
  data() {
    return {
      test: "測(cè)試",
    };
  },
  methods: {
    changeTest() {
      this.test = "測(cè)試后";
    }
  }
};
</script>

//son組件
<template>
  <div>{{injectData}}</div>
</template>


<script>
export default {
  name: "son",
  inject: ["injectData"],
  mounted() {
    // eslint-disable-next-line
    console.log(this.injectData)
  },
};
</script>

parent組件使用provide提供一個(gè)injectDatason組件通過inject獲取到parent注入的數(shù)據(jù),以上就是它的最簡(jiǎn)用法。有一點(diǎn)需要注意,我們可以將inject得到的數(shù)據(jù)直接賦值給子組件的dataprops,但是這個(gè)是在vue版本2.1之后才有的功能,這版本之前,會(huì)在data,props得到之后再得到注入的值。

使用provide/inject我們需要注意的是:

provide/inject這對(duì)選項(xiàng)需要一起使用,以允許一個(gè)祖先組件向其所有子孫后代注入一個(gè)依賴,不論組件層次有多深,并在起上下游關(guān)系成立的時(shí)間里始終生效。
provide 選項(xiàng)應(yīng)該是:一個(gè)對(duì)象或返回一個(gè)對(duì)象的函數(shù)
inject 選項(xiàng)應(yīng)該是:一個(gè)字符串?dāng)?shù)組,或 一個(gè)對(duì)象,對(duì)象的 key 是本地的綁定名

如果我們parent組件里provide是如下代碼:

provide: {
    injectData: this.test
}

我們會(huì)發(fā)現(xiàn)this.test所得到的永遠(yuǎn)是undefined

 provide: {
      injectData:() => {
        //eslint-disable-next-line
        console.log(this)
      }
  },

我們打印出來的this永遠(yuǎn)是undefined,所以我們最好切記使用return返回一個(gè)對(duì)象,直接賦值對(duì)象僅在我們需要傳遞的是靜態(tài)數(shù)據(jù)時(shí)再使用。

最開始的例子測(cè)試中,我們會(huì)得到,provide傳遞的test數(shù)據(jù)并不是響應(yīng)式的,當(dāng)parent改變了test的值后,son組件無法得到改變后的值,這就產(chǎn)生了一個(gè)問題,我們肯定是希望父子組件拿到的數(shù)據(jù)是相同的。

image.png

我們先看看官網(wǎng)是如何說的,哦,并不直接是可響應(yīng)的,而是要我們?nèi)藶槭顾强身憫?yīng)的,之前的測(cè)試是符合的,因?yàn)槲覀?code>provide的只是一個(gè)字符串,可響應(yīng)的我們很快想到對(duì)象,數(shù)組這些。這樣又產(chǎn)生一個(gè)問題,是provide傳遞的值就必須是個(gè)對(duì)象,還是說,傳遞的可以是個(gè)指針,指向的是個(gè)對(duì)象呢?實(shí)踐出真知,測(cè)試一下。

provide() {
    return {
      injectData: this.test
    };
  },
  data() {
    return {
      test: {
        test: "測(cè)試"
      },
    };
  },

我們先將provide的改成上面的,結(jié)果是響應(yīng)式的,我們?cè)贉y(cè)試一下另外一種。

provide() {
    return {
      injectData: {
        test: this.test
      }
    };
  },
  data() {
    return {
      test: "測(cè)試"
    };
  },

測(cè)試得出結(jié)果,上面的不是響應(yīng)式的。事實(shí)證明,必須是inject能拿到的數(shù)據(jù)對(duì)象響應(yīng)式,我們才能得到響應(yīng)式結(jié)果。

其實(shí)這樣也蠻麻煩的,比如如果父組件有超多需要傳遞下去的數(shù)據(jù),還有個(gè)超簡(jiǎn)潔的處理方式。

provide() {
  return {
      injectData: this
  }
}

我們可以將父組件整個(gè)傳遞到所需組件中去,并且組件實(shí)例本身就是響應(yīng)式的,這樣足以滿足我們大部分組件需求。

使用時(shí),我這邊還是遇到了一種場(chǎng)景,不是provide的問題,但是與之有點(diǎn)關(guān)系。當(dāng)我們將組件實(shí)例注入之后,子組件是能拿到組件的所有數(shù)據(jù)的,但是當(dāng)父組件內(nèi)里數(shù)據(jù)改變時(shí),子組件是監(jiān)聽不到數(shù)據(jù)的變化的,頁面也無法刷新,我是取了個(gè)巧,對(duì)數(shù)組進(jìn)行 splice或者concat等其他會(huì)觸發(fā)數(shù)組更新監(jiān)聽的操作,對(duì)象的話可以使用...Object.assign。$set沒什么用 ==!響應(yīng)式更新機(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 前言 組件是 vue.js最強(qiáng)大的功能之一,而組件實(shí)例的作用域是相互獨(dú)立的,這就意味著不同組件之間的數(shù)據(jù)無法相互引...
    Vicky丶Amor閱讀 6,121評(píng)論 10 162
  • 摘要: 總有一款合適的通信方式。 作者:浪里行舟 Fundebug經(jīng)授權(quán)轉(zhuǎn)載,版權(quán)歸原作者所有。 前言 組件是 v...
    Fundebug閱讀 15,646評(píng)論 3 57
  • 前言 組件是 vue.js最強(qiáng)大的功能之一,而組件實(shí)例的作用域是相互獨(dú)立的,這就意味著不同組件之間的數(shù)據(jù)無法相互引...
    浪里行舟閱讀 8,763評(píng)論 0 49
  • provide/inject深入學(xué)習(xí) 本文深入探究provide,inject 在官網(wǎng)porivide, inje...
    joyer_li閱讀 3,060評(píng)論 0 4
  • 01 男孩為什么靜不下來? 男孩血液中的多巴胺含量較多,流經(jīng)小腦的血量更多。多巴胺可增加沖動(dòng)和冒險(xiǎn)行為的概率。而小...
    布谷親子閱讀 738評(píng)論 0 0

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