91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue2響應式系統之嵌套怎么實現

發布時間:2022-04-13 10:24:52 來源:億速云 閱讀:190 作者:iii 欄目:開發技術

這篇“Vue2響應式系統之嵌套怎么實現”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Vue2響應式系統之嵌套怎么實現”文章吧。

1、場景

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

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

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

回到我們之前的響應式系統,模擬一下上邊的情況:

import { observe } from "./reactive";
import Watcher from "./watcher";
const data = {
    text: "hello, world",
    inner: "內部",
};
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

第一步是保存當前函數,然后執行當前函數前將全局的 賦值為當前 對象。Dep.targetWatcher

Vue2響應式系統之嵌套怎么實現

接下來執行 函數的時候,如果讀取了相應的屬性就會觸發 ,從而將當前 收集到該屬性的 中。gettergetWatcherDep

Vue2響應式系統之嵌套怎么實現

2、執行過程

import { observe } from "./reactive";
import Watcher from "./watcher";
const data = {
    text: "hello, world",
    inner: "內部",
};
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);

將 賦值為保存了 函數的 。Dep.targetupdateParentComponentWatcher

接下來執行 函數。updateParentComponent

  • new Watcher(updateMyComponent);

將 賦值為保存了 函數的 。Dep.targetupdateMyComponentWatcher

接下來執行 函數。updateMyComponent

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

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

data.text = "hello, liang";

觸發 的 函數,執行它依賴的 ,而此時是 函數。textsetWatcherupdateMyComponent

所以上邊代碼最終輸出的結果是:

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

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

3、修復

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

回憶一下學習 語言或者匯編語言的時候對函數參數的處理:C

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

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

a("parent");

當函數發生嵌套調用的時候,執行 函數的時候我們會先將參數壓入棧中,然后執行 函數,同樣將參數壓入棧中, 函數執行完畢就將參數出棧。此時回到 函數就能正確取到 參數的值了。abbap

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

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

import { remove } from "./util";

let uid = 0;

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

// 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]; // 賦值為棧頂元素
}

然后 中,執行函數之前進行入棧,執行后進行出棧。Watcher

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

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

4、測試

回到開頭的場景,再來執行一下:

import { observe } from "./reactive";
import Watcher from "./watcher";
const data = {
    text: "hello, world",
    inner: "內部",
};
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);Watcher

Vue2響應式系統之嵌套怎么實現

進入 函數,執行 的時候將 入棧。updateParentComponentnew Watcher(updateMyComponent);Watcher

Vue2響應式系統之嵌套怎么實現

執行 函數, 收集當前 ,執行完畢后 出棧。updateMyComponentdata.innerDep.targetWatcher

Vue2響應式系統之嵌套怎么實現

繼續執行 函數, 收集當前 。updateParentComponentdata.textDep.target

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

子組件收到: 內部
父組件收到: hello, world
子組件收到: 內部
父組件收到: hello, liang

以上就是關于“Vue2響應式系統之嵌套怎么實現”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

vue
AI

玛纳斯县| 澜沧| 府谷县| 孟州市| 米易县| 鄢陵县| 阆中市| 内乡县| 涿鹿县| 奉节县| 义乌市| 宣威市| 包头市| 长葛市| 普陀区| 花垣县| 花莲市| 余干县| 西充县| 蒲江县| 日土县| 东乌| 崇礼县| 漠河县| 宜阳县| 柳州市| 武汉市| 德清县| 德惠市| 舟曲县| 叙永县| 大庆市| 林芝县| 潜山县| 陕西省| 方城县| 黔南| 钟祥市| 九寨沟县| 双鸭山市| 且末县|