亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

一文搞懂vue中provide和inject實現(xiàn)原理對抗平庸

 更新時間:2023年04月16日 12:02:00   作者:陪我去看海  
這篇文章主要為大家介紹了vue中provide和inject實現(xiàn)原理的深入理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

在沒有面試又似乎馬上就會有面試的躁動不安的日子里,迷迷糊糊的看到一個面試題“你知道provide和inject的實現(xiàn)原理嗎”,我學(xué)著面試官的樣子試問自己"你知道嗎",我的大腦翻遍了記憶,也沒有找到,可能是沒有記載,亦可能是時間過長被積壓在了記憶深處,我始終沒有回答我自己,這讓我非常懊惱,又滿是無奈。所以我想搞懂它,用它的原理來撫平我的內(nèi)心。

provide & inject 的用法

provide("num", 0);
const num = inject("num")

這大致就是它們的美貌,它們示人的一面,如此優(yōu)雅,如此簡潔。它們隱藏了內(nèi)心,從這里讓我無法了解到它的內(nèi)心它到底在想什么呢,在做什么呢,我嘗試著與它親近,逐漸發(fā)現(xiàn)它的有趣。

在provide中,它留了兩個深入了解它的窗口provide(key, value),同樣在inject中,目前只能看到一個inject(key),結(jié)合它們的功能知道,它們的主要功能不就是存和取,所以想要了解它們就要搞清楚如何存,怎么取,先讓這疑問留在心底罷,來看看"下面例子"

下面例子

有這樣一串代碼,讓我們實現(xiàn)provide 和 inject這兩個函數(shù),達到在foo對象中的fooObj取的是app對象中provide提供的對象obj,我們?nèi)绾螌崿F(xiàn)

const obj = { name: "app" };
const foo = {
  name: "foo",
  provides: {},
  parent: null,
  setup() {
    foo.parent = app; // 先忽略
    const fooObj = inject("obj");
    console.log("app -> foo: obj ", fooObj === obj); // 要求打印true
  },
  children: null,
};
const app = {
  name: "app",
  provides: {},
  parent: null,
  setup() {
    app.parent = app; // 先忽略
    provide("obj", obj);
  },
  children: foo,
};
(function () {
  app.setup();
  foo.setup();
})();

需要實現(xiàn)什么

首先我們需要明確我們要干什么:

  • 其實本質(zhì)就是要實現(xiàn)provide和inject函數(shù)
  • 明確代碼在做什么
  • 有兩個對象app 和 foo,它兩長得一樣美麗,初始化階段,它兩內(nèi)部的setup方法會依次執(zhí)行,在內(nèi)部它們分別使用了provide提供數(shù)據(jù),以及使用inject獲取數(shù)據(jù),要求fooObj === obj為true,這其實就是判斷是否是同一個數(shù)據(jù)的根本方法。

知道了這些后,我們一起來認識一下provide和inject吧,我們以主觀意識去了解它們,把我認為它是什么樣子畫出來。

首先畫出它的骨架:

function provide(key, value) {
    // 靈魂深處
}
function inject(key) {
    // 靈魂深處
}

我們要一起探聽我們理想中它們的靈魂

內(nèi)心中的呈現(xiàn)

provide分析

  • 提供了key-value
  • 我們需要存儲在各自對象中的provides屬性中
function provide(key, value) {
  // 獲取當前提供provide的對象
  const currentInstance = app;
  // 將provide提供的key-value存儲到當前對象的provides中
  let { provides } = currentInstance;
  provides[key] = value;
}

inject分析

  • 從parent下的provides開始取值,因為在自己這里提供的provide不需要進行inject,多此一舉
function inject(key) {
  const currentInstance = foo;
  // 從parent的provides取值
  const parentProvides = currentInstance.parent.provides;
  // 如果提供了值,就可以取到并返回
  if (key in parentProvides) {
    return parentProvides[key];
  }
}

這時候我們可以打印出(fooObj === obj) === true了

在沉浸喜悅的同時,在provide和inject靈魂處蹦出字來你還是不夠了解我,我仔細思考,好像也是,它們還有一個特性就是跨層級,這恰恰是遺忘了它最有靈魂的地方,所以我們重新規(guī)劃下面例子

下面例子

const obj = { name: "app" };
const baz = {
  name: "foo",
  provides: {},
  parent: null,
  setup() {
    baz.parent = foo;
    const bazObj = inject("obj");
    console.log("app -> baz: obj ", bazObj === obj); // 要求打印true
  },
  children: null,
};
const foo = {
  name: "foo",
  provides: {},
  parent: null,
  setup() {
    foo.parent = app;
  },
  children: baz,
};
const app = {
  name: "app",
  provides: {},
  parent: null,
  setup() {
    app.parent = app;
    provide("obj", obj);
  },
  children: foo,
};
(function () {
  app.setup();
  foo.setup();
  baz.setup();
})();

這時候就會打印false了PS: 如果你還是true,那是因為你在 inject 里 currentInstance沒有改變,這里是需要改變的,只能指到當前對象,所以我們?nèi)绾谓鉀Q呢?

這里說到如果currentInstance 是 foo,那就沒有問題,但是又因為這里是只能指向當前對象的,所以不能直接賦值,突然,靈光一閃,無非不就是查找的時候需要繼續(xù)向下查找,這不是和原型鏈一樣嘛內(nèi)心:哈哈哈,我真聰明,所以我們給它進行原型連接不就好了,讓一直向parent上找,直到找不到。

跨層級查找

進行原型連接,實現(xiàn)跨層級:Object.create(obj): 創(chuàng)造一個原型為obj的空對象

const foo = {
  name: "foo",
  provides: {},
  parent: null,
  setup() {
    foo.parent = app;
    // 執(zhí)行原型連接
    foo.provides = Object.create(foo.parent.provides);
  },
  children: baz,
};

這樣就又打印true了,因為它直接在foo.provides上查找,無法找到提供的obj所以會undefined,原型連接后,查找會順著原型鏈查找,直到找不到,那找不到的時候怎么辦呢,它會報錯的呀,這是不能容忍的,所以inject向我敞開心扉,和我聊自己是怎么樣的一個API,它說:"我其實有三種外貌,對應(yīng)不同心情,分別是inject(key)、inject(key, defaultValue)和 defaultValue 可以是函數(shù)",至此我們之間的關(guān)系好像又進一步,我好像更了解它們了。

inject放下偽裝,吐露心聲

inject 的形態(tài):

  • inject(key) —— 已實現(xiàn)
  • inject(key, defaultValue) —— 未實現(xiàn)
  • inject(key, () => defaultValue) —— 未實現(xiàn)

回顧一下inject:

function inject(key) {
  const currentInstance = baz;
  const parentProvides = currentInstance.parent.provides;
  if (key in parentProvides) {
    return parentProvides[key];
  }
}

這是我們最后實現(xiàn)inject的樣子,這會inject告訴了我們其他狀態(tài),所以我們需要和它更進一步,它會提供一個defaultValue屬性,所以我們在parent鏈中沒有找到key的時候,就需要賦值defaultValue了

function inject(key, defaultValue) {
  const currentInstance = baz;
  const parentProvides = currentInstance.parent.provides;
  // 當沒有在 parent 鏈中找到對應(yīng)key,就返回默認值
  if (key in parentProvides) {
    return parentProvides[key];
  } else if (defaultValue) {
    return defaultValue;
  }
}

將baz對象修改為:

const baz = {
  name: "foo",
  provides: {},
  parent: null,
  setup() {
    baz.parent = foo;
    const defaultBaz = inject("baz", "我是默認值啦!");
    console.log(defaultBaz, "baz");
  },
  children: null,
};

打印出了:我是默認值啦!

但是當defaultValue是回調(diào)函數(shù)的時候,我們所以需要添加判斷條件,如果是回調(diào)函數(shù),那就直接執(zhí)行。

修改后的inject:

function inject(key, defaultValue) {
  const currentInstance = baz;
  const parentProvides = currentInstance.parent.provides;
  if (key in parentProvides) {
    return parentProvides[key];
  } else if (defaultValue) {
    // 新增判斷
    if (typeof defaultValue === "function") {
      return defaultValue();
    }
    return defaultValue;
  }
}

修改后的baz中的inject使用:

const defaultBaz = inject("baz", () => "我是默認值啦!");

同樣也會打印出:我是默認值啦!

現(xiàn)在我們好像成為好朋友了,所以,你好,provide!你好,inject!你們好,各位大帥b!

總結(jié)

  • 每個provide提供的數(shù)據(jù)都存在當前組件的provides屬性上
  • inject取值的時候,會從當前的父組件中的provides開始取值
  • 其實已經(jīng)懂了 provide 和 inject 原理了,因為在Vue中,他的每個組件也會生成組件實例,而這些屬性全都在實例對象上。

以上就是一文搞懂vue中provide和inject實現(xiàn)原理對抗平庸的詳細內(nèi)容,更多關(guān)于vue provide inject實現(xiàn)原理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論