欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue3全局組件通信之provide?/?inject詳解

 更新時間:2023年03月14日 14:53:01   作者:老電影故事  
這篇文章主要介紹了Vue3全局組件通信之provide?/?inject,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

1、前言

顧名思義,爺孫組件是比 父子組件通信 要更深層次的引用關(guān)系(也有稱之為 “隔代組件”):

C組件引入到B組件里,B組件引入到A組件里渲染,此時A是C的爺爺級別(可能還有更多層級關(guān)系),如果你用 props ,只能一級一級傳遞下去,那就太繁瑣了,因此我們需要更直接的通信方式。

他們之間的關(guān)系如下,Grandson.vue 并非直接掛載在 Grandfather.vue 下面,他們之間還隔著至少一個 Son.vue (可能有多個):

Grandfather.vue
└─Son.vue
  └─Grandson.vue

??????
因為上下級的關(guān)系的一致性,爺孫組件通信的方案也適用于 父子組件通信 ,只需要把爺孫關(guān)系換成父子關(guān)系即可。

2、provide / inject

這個特性有兩個部分:Grandfather.vue 有一個 provide 選項來提供數(shù)據(jù),Grandson.vue 有一個 inject 選項來開始使用這些數(shù)據(jù)。

  • Grandfather.vue 通過 provide 向 Grandson.vue 傳值(可包含定義好的函數(shù))
  • Grandson.vue 通過 inject 向 Grandfather.vue 觸發(fā)爺爺組件的事件執(zhí)行

??????
無論組件層次結(jié)構(gòu)有多深,發(fā)起 provide 的組件都可以作為其所有下級組件的依賴提供者
這一部分的內(nèi)容變化都特別大,但使用起來其實也很簡單,不用慌,也有相同的地方:

  • 父組件不需要知道哪些子組件使用它 provide 的 property
  • 子組件不需要知道 inject property 來自哪里

另外,要切記一點就是:provide 和 inject 綁定并不是可響應(yīng)的。這是刻意為之的,但如果傳入了一個可監(jiān)聽的對象,那么其對象的 property 還是可響應(yīng)的。

3、發(fā)起 provide

我們先來回顧一下 2.x 的用法:

export default {
  // 定義好數(shù)據(jù)
  data () {
    return {
      tags: [ '中餐', '粵菜', '燒臘' ]
    }
  },
  // provide出去
  provide () {
    return {
      tags: this.tags
    }
  }
}

舊版的 provide 用法和 data 類似,都是配置為一個返回對象的函數(shù)。
3.x 的新版 provide, 和 2.x 的用法區(qū)別比較大。

??????
在 3.x , provide 需要導入并在 setup 里啟用,并且現(xiàn)在是一個全新的方法。
每次要 provide 一個數(shù)據(jù)的時候,就要單獨調(diào)用一次。
每次調(diào)用的時候,都需要傳入 2 個參數(shù):

參數(shù)類型說明
keystring數(shù)據(jù)的名稱
valueany數(shù)據(jù)的值

來看一下如何創(chuàng)建一個 provide:

// 記得導入provide
import { defineComponent, provide } from 'vue'

export default defineComponent({
  // ...
  setup () {
    // 定義好數(shù)據(jù)
    const msg: string = 'Hello World!';

    // provide出去
    provide('msg', msg);
  }
})

操作非常簡單對吧,但需要注意的是,provide 不是響應(yīng)式的,如果你要使其具備響應(yīng)性,你需要傳入響應(yīng)式數(shù)據(jù)

4、接收 inject

也是先來回顧一下 2.x 的用法:

export default {
  inject: ['tags'],
  mounted () {
    console.log(this.tags);
  }
}

舊版的 inject 用法和 props 類似,3.x 的新版 inject, 和 2.x 的用法區(qū)別也是比較大。

??????
在 3.x, inject 和 provide 一樣,也是需要先導入然后在 setup 里啟用,也是一個全新的方法。
每次要 inject 一個數(shù)據(jù)的時候,就要單獨調(diào)用一次。
每次調(diào)用的時候,只需要傳入 1 個參數(shù):

參數(shù)類型說明
keystring與provide對應(yīng)的數(shù)據(jù)名稱
// 記得導入inject
import { defineComponent, inject } from 'vue'

export default defineComponent({
  // ...
  setup () {
    const msg: string = inject('msg') || '';
  }
})

也是很簡單(寫 TS 的話,由于 inject 到的值可能是 undefined,所以要么加個 undefined 類型,要么給變量設(shè)置一個空的默認值)。

5、響應(yīng)性數(shù)據(jù)的傳遞與接收

之所以要單獨拿出來說, 是因為變化真的很大

在前面我們已經(jīng)知道,provide 和 inject 本身不可響應(yīng),但是并非完全不能夠拿到響應(yīng)的結(jié)果,只需要我們傳入的數(shù)據(jù)具備響應(yīng)性,它依然能夠提供響應(yīng)支持。

我們以 ref 和 reactive 為例,來看看應(yīng)該怎么發(fā)起 provide 和接收 inject。

先在 Grandfather.vue 里 provide 數(shù)據(jù):

export default defineComponent({
  // ...
  setup () {
    // provide一個ref
    const msg = ref<string>('Hello World!');
    provide('msg', msg);

    // provide一個reactive
    const userInfo: Member = reactive({
      id: 1,
      name: 'Petter'
    });
    provide('userInfo', userInfo);

    // 2s 后更新數(shù)據(jù)
    setTimeout(() => {
      // 修改消息內(nèi)容
      msg.value = 'Hi World!';

      // 修改用戶名
      userInfo.name = 'Tom';
    }, 2000);
  }
})

在 Grandsun.vue 里 inject 拿到數(shù)據(jù):

export default defineComponent({
  setup () {
    // 獲取數(shù)據(jù)
    const msg = inject('msg');
    const userInfo = inject('userInfo');

    // 打印剛剛拿到的數(shù)據(jù)
    console.log(msg);
    console.log(userInfo);

    // 因為 2s 后數(shù)據(jù)會變,我們 3s 后再看下,可以爭取拿到新的數(shù)據(jù)
    setTimeout(() => {
      console.log(msg);
      console.log(userInfo);
    }, 3000);

    // 響應(yīng)式數(shù)據(jù)還可以直接給 template 使用,會實時更新
    return {
      msg,
      userInfo
    }
  }
})

非常簡單,非常方便?。。?/p>

??????
響應(yīng)式的數(shù)據(jù) provide 出去,在子孫組件拿到的也是響應(yīng)式的,并且可以如同自身定義的響應(yīng)式變量一樣,直接 return 給 template 使用,一旦數(shù)據(jù)有變化,視圖也會立即更新。

但上面這句話有效的前提是,不破壞數(shù)據(jù)的響應(yīng)性,比如 ref 變量,你需要完整的傳入,而不能只傳入它的 value,對于 reactive 也是同理,不能直接解構(gòu)去破壞原本的響應(yīng)性。

切記!切記?。?!

6、引用類型的傳遞與接收 (針對非響應(yīng)性數(shù)據(jù)的處理)

provide 和 inject 并不是可響應(yīng)的,這是官方的故意設(shè)計,但是由于引用類型的特殊性,在子孫組件拿到了數(shù)據(jù)之后,他們的屬性還是可以正常的響應(yīng)變化。

先在 Grandfather.vue 里 provide 數(shù)據(jù):

export default defineComponent({
  // ...
  setup () {
    // provide 一個數(shù)組
    const tags: string[] = [ '中餐', '粵菜', '燒臘' ];
    provide('tags', tags);

    // provide 一個對象
    const userInfo: Member = {
      id: 1,
      name: 'Petter'
    };
    provide('userInfo', userInfo);

    // 2s 后更新數(shù)據(jù)
    setTimeout(() => {
      // 增加tags的長度
      tags.push('叉燒');

      // 修改userInfo的屬性值
      userInfo.name = 'Tom';
    }, 2000);
  }
})

在 Grandsun.vue 里 inject 拿到數(shù)據(jù):

export default defineComponent({
  setup () {
    // 獲取數(shù)據(jù)
    const tags: string[] = inject('tags') || [];
    const userInfo: Member = inject('userInfo') || {
      id: 0,
      name: ''
    };

    // 打印剛剛拿到的數(shù)據(jù)
    console.log(tags);
    console.log(tags.length);
    console.log(userInfo);

    // 因為 2s 后數(shù)據(jù)會變,我們 3s 后再看下,能夠看到已經(jīng)是更新后的數(shù)據(jù)了
    setTimeout(() => {
      console.log(tags);
      console.log(tags.length);
      console.log(userInfo);
    }, 3000);
  }
})

export default defineComponent({
  setup () {
    // 獲取數(shù)據(jù)
    const tags: string[] = inject('tags') || [];
    const userInfo: Member = inject('userInfo') || {
      id: 0,
      name: ''
    };

    // 打印剛剛拿到的數(shù)據(jù)
    console.log(tags);
    console.log(tags.length);
    console.log(userInfo);

    // 因為 2s 后數(shù)據(jù)會變,我們 3s 后再看下,能夠看到已經(jīng)是更新后的數(shù)據(jù)了
    setTimeout(() => {
      console.log(tags);
      console.log(tags.length);
      console.log(userInfo);
    }, 3000);
  }
})

??????
引用類型的數(shù)據(jù),拿到后可以直接用,屬性的值更新后,子孫組件也會被更新。
但是?。?!由于不具備真正的響應(yīng)性,return 給模板使用依然不會更新視圖,如果涉及到視圖的數(shù)據(jù),請依然使用 響應(yīng)式 API 。

7、基本類型的傳遞與接收 (針對非響應(yīng)性數(shù)據(jù)的處理)

基本數(shù)據(jù)類型被直接 provide 出去后,再怎么修改,都無法更新下去,子孫組件拿到的永遠是第一次的那個值。

先在 Grandfather.vue 里 provide 數(shù)據(jù):

export default defineComponent({
  // ...
  setup () {
    // provide 一個數(shù)組的長度
    const tags: string[] = [ '中餐', '粵菜', '燒臘' ];
    provide('tagsCount', tags.length);

    // provide 一個字符串
    let name: string = 'Petter';
    provide('name', name);

    // 2s 后更新數(shù)據(jù)
    setTimeout(() => {
      // tagsCount 在 Grandson 那邊依然是 3
      tags.push('叉燒');

      // name 在 Grandson 那邊依然是 Petter
      name = 'Tom';
    }, 2000);
  }
})

在 Grandsun.vue 里 inject 拿到數(shù)據(jù):

export default defineComponent({
  setup () {
    // 獲取數(shù)據(jù)
    const name: string = inject('name') || '';
    const tagsCount: number = inject('tagsCount') || 0;

    // 打印剛剛拿到的數(shù)據(jù)
    console.log(name);
    console.log(tagsCount);

    // 因為 2s 后數(shù)據(jù)會變,我們 3s 后再看下
    setTimeout(() => {
      // 依然是 Petter
      console.log(name);

      // 依然是 3
      console.log(tagsCount);
    }, 3000);
  }
})

很失望,并沒有變化。

??????
那么是否一定要定義成響應(yīng)式數(shù)據(jù)或者引用類型數(shù)據(jù)呢?

當然不是,我們在 provide 的時候,也可以稍作修改,讓它能夠同步更新下去。

先在 Grandfather.vue 里 provide 數(shù)據(jù):

export default defineComponent({
  // ...
  setup () {
    // provide 一個數(shù)組的長度
    const tags: string[] = [ '中餐', '粵菜', '燒臘' ];
    provide('tagsCount', (): number => {
      return tags.length;
    });

    // provide 字符串
    let name: string = 'Petter';
    provide('name', (): string => {
      return name;
    });

    // 2s 后更新數(shù)據(jù)
    setTimeout(() => {
      // tagsCount 現(xiàn)在可以正常拿到 4 了
      tags.push('叉燒');

      // name 現(xiàn)在可以正常拿到 Tom 了
      name = 'Tom';
    }, 2000);
  }
})

再來 Grandsun.vue 里修改一下 inject 的方式,看看這次拿到的數(shù)據(jù):

export default defineComponent({
  setup () {
    // 獲取數(shù)據(jù)
    const tagsCount: any = inject('tagsCount');
    const name: any = inject('name');

    // 打印剛剛拿到的數(shù)據(jù)
    console.log(tagsCount());
    console.log(name());

    // 因為 2s 后數(shù)據(jù)會變,我們 3s 后再看下
    setTimeout(() => {
      // 現(xiàn)在可以正確得到 4
      console.log(tagsCount());

      // 現(xiàn)在可以正確得到 Tom
      console.log(name());
    }, 3000);
  }
})

這次可以正確拿到數(shù)據(jù)了,看出這2次的寫法有什么區(qū)別了嗎?

??????
基本數(shù)據(jù)類型,需要 provide 一個函數(shù),將其 return 出去給子孫組件用,這樣子孫組件每次拿到的數(shù)據(jù)才會是新的。
但由于不具備響應(yīng)性,所以子孫組件每次都需要重新通過執(zhí)行 inject 得到的函數(shù)才能拿到最新的數(shù)據(jù)。

按我個人習慣來說,使用起來挺別扭的,能不用就不用……

由于不具備真正的響應(yīng)性,return 給模板使用依然不會更新視圖,如果涉及到視圖的數(shù)據(jù),請依然使用 響應(yīng)式 API 。

到此這篇關(guān)于Vue3全局組件通信之provide / inject的文章就介紹到這了,更多相關(guān)Vue3全局組件通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • karma+webpack搭建vue單元測試環(huán)境的方法示例

    karma+webpack搭建vue單元測試環(huán)境的方法示例

    本篇文章主要介紹了karma+webpack搭建vue單元測試環(huán)境的方法示例,這次搭建的測試環(huán)境和開發(fā)環(huán)境隔離,所以理論上適用所有使用vue的開發(fā)環(huán)境。感興趣的小伙伴們可以參考一下
    2018-05-05
  • 詳解vue 模版組件的三種用法

    詳解vue 模版組件的三種用法

    本篇文章主要介紹了詳解vue 模版組件的三種用法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • 使用Element的InfiniteScroll 無限滾動組件報錯的解決

    使用Element的InfiniteScroll 無限滾動組件報錯的解決

    這篇文章主要介紹了使用Element的InfiniteScroll 無限滾動組件報錯的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • vue electron應(yīng)用調(diào)exe程序的實現(xiàn)步驟

    vue electron應(yīng)用調(diào)exe程序的實現(xiàn)步驟

    這篇文章主要介紹了vue electron應(yīng)用調(diào)exe程序的實現(xiàn)步驟,用Python寫了一個本地服務(wù)編譯成exe程序,在electron程序啟動后,自動執(zhí)行exe程序,文中有詳細的代碼示例供大家參考,需要的朋友可以參考下
    2024-02-02
  • 詳解vue-admin和后端(flask)分離結(jié)合的例子

    詳解vue-admin和后端(flask)分離結(jié)合的例子

    本篇文章主要介紹了詳解vue-admin和后端(flask)分離結(jié)合的例子,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-02-02
  • vue引入iconfont圖標庫的優(yōu)雅實戰(zhàn)記錄

    vue引入iconfont圖標庫的優(yōu)雅實戰(zhàn)記錄

    使用組件庫時,圖標往往不能滿足需求,所以我們常常需要用到第三方圖標庫,這篇文章主要給大家介紹了關(guān)于vue引入iconfont的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • vue中關(guān)于element的el-image 圖片預覽功能增加一個下載按鈕(操作方法)

    vue中關(guān)于element的el-image 圖片預覽功能增加一個下載按鈕(操作方法)

    這篇文章主要介紹了vue中關(guān)于element的el-image 圖片預覽功能增加一個下載按鈕,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • 基于node+vue實現(xiàn)簡單的WebSocket聊天功能

    基于node+vue實現(xiàn)簡單的WebSocket聊天功能

    最近學習了一下websocket的即時通信,感覺非常的強大,這里我用node啟動了一個服務(wù)進行websocket鏈接,然后再vue的view里面進行了鏈接,進行通信,廢話不多說,直接上代碼吧
    2020-02-02
  • vue axios重復點擊取消上一次請求封裝的方法

    vue axios重復點擊取消上一次請求封裝的方法

    這篇文章主要介紹了vue axios重復點擊取消上一次請求封裝的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-06-06
  • Vue路由切換的兩種方式示例詳解

    Vue路由切換的兩種方式示例詳解

    這篇文章主要介紹了Vue路由切換的兩種方式,主要包括標簽切換和js切換,本文結(jié)合示例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-12-12

最新評論