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

Vue2響應(yīng)式系統(tǒng)之嵌套

 更新時間:2022年04月12日 20:10:18   作者:windliang  
這篇文章主要介紹了Vue響應(yīng)式系統(tǒng)之嵌套,我們在開發(fā)中肯定存在組件嵌套組件的情況,下文將舉例說明情況,需要的小伙伴可以參考一下

1、場景

在 開發(fā)中肯定存在組件嵌套組件的情況,類似于下邊的樣子。Vue

<!-- parent-component -->
<div>
  <my-component :text="inner"></my-component>
  {{ text }}
<div>

<!-- my-component-->
<div>{{ text }}</div>

回到我們之前的響應(yīng)式系統(tǒng),模擬一下上邊的情況:

import { observe } from "./reactive";
import Watcher from "./watcher";
const data = {
    text: "hello, world",
    inner: "內(nèi)部",
};
observe(data);

const updateMyComponent = () => {
    console.log("子組件收到:", data.inner);
};

const updateParentComponent = () => {
    new Watcher(updateMyComponent);
    console.log("父組件收到:", data.text);
};

new Watcher(updateParentComponent);

data.text = "hello, liang";

可以先 分鐘考慮一下上邊輸出什么?1

首先回憶一下 會做什么操作。new Watcher

第一步是保存當(dāng)前函數(shù),然后執(zhí)行當(dāng)前函數(shù)前將全局的 賦值為當(dāng)前 對象。Dep.targetWatcher

image-20220402083845476

接下來執(zhí)行 函數(shù)的時候,如果讀取了相應(yīng)的屬性就會觸發(fā) ,從而將當(dāng)前 收集到該屬性的 中。gettergetWatcherDep

image-20220402083943606

2、執(zhí)行過程

import { observe } from "./reactive";
import Watcher from "./watcher";
const data = {
    text: "hello, world",
    inner: "內(nèi)部",
};
observe(data);

const updateMyComponent = () => {
    console.log("子組件收到:", data.inner);
};

const updateParentComponent = () => {
    new Watcher(updateMyComponent);
    console.log("父組件收到:", data.text);
};

new Watcher(updateParentComponent);

data.text = "hello, liang";

我們再一步一步理清一下:

  • new Watcher(updateParentComponent);

將 賦值為保存了 函數(shù)的 。Dep.targetupdateParentComponentWatcher

接下來執(zhí)行 函數(shù)。updateParentComponent

  • new Watcher(updateMyComponent);

將 賦值為保存了 函數(shù)的 。Dep.targetupdateMyComponentWatcher

接下來執(zhí)行 函數(shù)。updateMyComponent

const updateMyComponent = () => {
    console.log("子組件收到:", data.inner);
};

// 讀取了 inner 變量。
// data.inner 的 Dep 收集當(dāng)前 Watcher(保存了 `updateMyComponent` 函數(shù))
const updateParentComponent = () => {
    new Watcher(updateMyComponent);
    console.log("父組件收到:", data.text);
};
// 讀取了 text 變量。
// data.text 的 Dep 收集當(dāng)前 Watcher (保存了 `updateMyComponent` 函數(shù))

data.text = "hello, liang";

觸發(fā) 的 函數(shù),執(zhí)行它依賴的 ,而此時是 函數(shù)。textsetWatcherupdateMyComponent

所以上邊代碼最終輸出的結(jié)果是:

子組件收到: 內(nèi)部  // new Watcher(updateMyComponent); 時候輸出
父組件收到: hello, world // new Watcher(updateParentComponent); 時候輸出
子組件收到: 內(nèi)部 // data.text = "hello, liang"; 輸出

然而子組件并不依賴 ,依賴 的父組件反而沒有執(zhí)行。data.textdata.text

3、修復(fù)

上邊的問題出在我們保存當(dāng)前正在執(zhí)行 時候使用的是單個變量 。WatcherDep.target = null; // 靜態(tài)變量,全局唯一

回憶一下學(xué)習(xí) 語言或者匯編語言的時候?qū)瘮?shù)參數(shù)的處理:C

function b(p) {
    console.log(p);
}

function a(p) {
    b("child");
    console.log(p);
}

a("parent");

當(dāng)函數(shù)發(fā)生嵌套調(diào)用的時候,執(zhí)行 函數(shù)的時候我們會先將參數(shù)壓入棧中,然后執(zhí)行 函數(shù),同樣將參數(shù)壓入棧中, 函數(shù)執(zhí)行完畢就將參數(shù)出棧。此時回到 函數(shù)就能正確取到 參數(shù)的值了。abbap

對應(yīng)于 的收集,我們同樣可以使用一個棧來保存,執(zhí)行函數(shù)前將 壓入棧,執(zhí)行函數(shù)完畢后將 彈出棧即可。其中, 始終指向棧頂 ,代表當(dāng)前正在執(zhí)行的函數(shù)。WatcherWatcherWatcherDep.targetWatcher

回到 代碼中,我們提供一個壓棧和出棧的方法。Dep

import { remove } from "./util";

let uid = 0;

export default class Dep {
    ... 省略
}
Dep.target = null; // 靜態(tài)變量,全局唯一

// The current target watcher being evaluated.
// This is globally unique because only one watcher
// can be evaluated at a time.
const targetStack = [];

export function pushTarget(target) {
    targetStack.push(target);
    Dep.target = target;
}

export function popTarget() {
    targetStack.pop();
    Dep.target = targetStack[targetStack.length - 1]; // 賦值為棧頂元素
}

然后 中,執(zhí)行函數(shù)之前進(jìn)行入棧,執(zhí)行后進(jìn)行出棧。Watcher

import { pushTarget, popTarget } from "./dep";
export default class Watcher {
    constructor(Fn) {
        this.getter = Fn;
        this.depIds = new Set(); // 擁有 has 函數(shù)可以判斷是否存在某個 id
        this.deps = [];
        this.newDeps = []; // 記錄新一次的依賴
        this.newDepIds = new Set();
        this.get();
    }

    /**
     * Evaluate the getter, and re-collect dependencies.
     */
    get() {
      /************修改的地方*******************************/
        pushTarget(this); // 保存包裝了當(dāng)前正在執(zhí)行的函數(shù)的 Watcher
       /*******************************************/
        let value;
        try {
            value = this.getter.call();
        } catch (e) {
            throw e;
        } finally {
          /************修改的地方*******************************/
            popTarget();
          /*******************************************/
            this.cleanupDeps();
        }
        return value;
    }
   ...
}

4、測試

回到開頭的場景,再來執(zhí)行一下:

import { observe } from "./reactive";
import Watcher from "./watcher";
const data = {
    text: "hello, world",
    inner: "內(nèi)部",
};
observe(data);

const updateMyComponent = () => {
    console.log("子組件收到:", data.inner);
};

const updateParentComponent = () => {
    new Watcher(updateMyComponent);
    console.log("父組件收到:", data.text);
};

new Watcher(updateParentComponent);

data.text = "hello, liang";

執(zhí)行 的時候?qū)?nbsp;入棧。new Watcher(updateParentComponent);Watcher

image-20220402093847759

進(jìn)入 函數(shù),執(zhí)行 的時候?qū)?nbsp;入棧。updateParentComponentnew Watcher(updateMyComponent);Watcher

image-20220402093937896

執(zhí)行 函數(shù), 收集當(dāng)前 ,執(zhí)行完畢后 出棧。updateMyComponentdata.innerDep.targetWatcher

image-20220402093847759

繼續(xù)執(zhí)行 函數(shù), 收集當(dāng)前 。updateParentComponentdata.textDep.target

此時依賴就變得正常了, 會觸發(fā) 函數(shù),從而輸出如下:data.textupdateParentComponent

子組件收到: 內(nèi)部
父組件收到: hello, world
子組件收到: 內(nèi)部
父組件收到: hello, liang

5、總結(jié)

今天這個相對好理解一些,通過棧解決了嵌套調(diào)用的情況。

到此這篇關(guān)于Vue2響應(yīng)式系統(tǒng)之嵌套的文章就介紹到這了,更多相關(guān)Vue2 嵌套內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue3和Vite不得不說的那些事

    Vue3和Vite不得不說的那些事

    這篇文章主要為大家詳細(xì)介紹了Vue3和Vite的那些事,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • vue2.0多條件搜索組件使用詳解

    vue2.0多條件搜索組件使用詳解

    這篇文章主要為大家詳細(xì)介紹了vue2.0多條件搜索組件的實(shí)現(xiàn)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • vue @click與@click.native,及vue事件機(jī)制的使用分析

    vue @click與@click.native,及vue事件機(jī)制的使用分析

    這篇文章主要介紹了vue @click與@click.native,及vue事件機(jī)制的使用分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue3項(xiàng)目中優(yōu)雅實(shí)現(xiàn)微信授權(quán)登錄的方法

    Vue3項(xiàng)目中優(yōu)雅實(shí)現(xiàn)微信授權(quán)登錄的方法

    用戶在微信端中訪問第三方網(wǎng)頁,可以通過微信網(wǎng)頁授權(quán)機(jī)制獲取用戶的基本信息,進(jìn)而實(shí)現(xiàn)所需要的業(yè)務(wù)邏輯,這篇文章主要給大家介紹了關(guān)于Vue3項(xiàng)目中優(yōu)雅實(shí)現(xiàn)微信授權(quán)登錄的相關(guān)資料,需要的朋友可以參考下
    2021-09-09
  • JavaScript實(shí)現(xiàn)簡單的圖片切換功能(實(shí)例代碼)

    JavaScript實(shí)現(xiàn)簡單的圖片切換功能(實(shí)例代碼)

    這篇文章主要介紹了JavaScript實(shí)現(xiàn)簡單的圖片切換功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2020-04-04
  • vue無限輪播插件代碼實(shí)例

    vue無限輪播插件代碼實(shí)例

    這篇文章主要介紹了vue無限輪播插件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • vue3使用拖拽組件draggable.next的保姆級教程

    vue3使用拖拽組件draggable.next的保姆級教程

    做項(xiàng)目的時候遇到了一個需求,拖拽按鈕到指定位置,添加一個輸入框,這篇文章主要給大家介紹了關(guān)于vue3使用拖拽組件draggable.next的保姆級教程,需要的朋友可以參考下
    2023-06-06
  • Vue自定義指令實(shí)現(xiàn)點(diǎn)擊右鍵彈出菜單示例詳解

    Vue自定義指令實(shí)現(xiàn)點(diǎn)擊右鍵彈出菜單示例詳解

    這篇文章主要為大家介紹了Vue自定義指令實(shí)現(xiàn)點(diǎn)擊右鍵彈出菜單示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • vue中使用閉包(防抖和節(jié)流)失效問題

    vue中使用閉包(防抖和節(jié)流)失效問題

    本文主要介紹了vue中使用閉包(防抖和節(jié)流)失效問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Vue導(dǎo)入excel表,導(dǎo)入失敗的數(shù)據(jù)自動下載

    Vue導(dǎo)入excel表,導(dǎo)入失敗的數(shù)據(jù)自動下載

    本文詳細(xì)講解了Vue導(dǎo)入excel表,導(dǎo)入失敗的數(shù)據(jù)自動下載的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-11-11

最新評論