国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【Vue原理】NextTick - 源碼版 之 服務(wù)Vue

Acceml / 1598人閱讀

寫文章不容易,點個贊唄兄弟
專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧
研究基于 Vue版本 【2.5.17】

如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧

【Vue原理】NextTick - 源碼版 之 服務(wù)Vue

初次看的兄弟可以先看 【Vue原理】NextTick - 白話版 簡單了解下NextTick

好的,今天,就來詳細記錄 Vue 和 nextTick 的那些事

nextTick 在 Vue 中,最重要的就是~~~

協(xié)助 Vue 進行更新操作!

上篇文章

NextTick-源碼版之獨立自身
提到過,nextTick 幫助 Vue 避免頻繁的更新,這里簡單提一下,

每次修改數(shù)據(jù),都會觸發(fā)數(shù)據(jù)的依賴更新

也就是說數(shù)據(jù)被修改的時候,會調(diào)用一遍【引用這個數(shù)據(jù)的實例】的更新函數(shù)

那么,按道理來說,修改3次,就應(yīng)該調(diào)用3遍更新函數(shù),但是實際上只會調(diào)用一遍

比如我們使用 watch 監(jiān)聽 data(data 便收集了 watch 的 watcher,監(jiān)聽回調(diào)就是更新函數(shù))

結(jié)果就是只打印一次

至于依賴更新,可以看下面的文章

依賴更新 - 源碼版

其實,修改數(shù)據(jù)能夠只更新一次,不止是 nextTick 起了作用,Vue 也做了其他處理,比如過濾實例,清空隊列等等,下面就來說一下

一切先從【實例更新函數(shù)】開始

第一個要說的就是 watcher!每個實例都有一個 watcher,然后 watcher 保存著實例的更新函數(shù)

每個實例都會通過 new Vue 生成的,所以會有一個專屬的 watcher

更新函數(shù)被保存在 watcher.getter 上

function Vue(){
    ....
    new Watcher(vm, 實例更新函數(shù))
}



function Watcher(vm, expOrFn) {    

    this.getter = expOrFn;

};



Watcher.prototype.get = function() {  

    this.getter.call(vm, vm);

};

Watcher.prototype.update = function() {
    queueWatcher(this);
};
Watcher.prototype.run = function() {  

    this.get();

};

我們知道, Vue 的 data 是響應(yīng)式的,就是通過 Object.defineProperty 設(shè)置 get 和 set

當(dāng)數(shù)據(jù)被修改的時候, set 函數(shù)被觸發(fā),函數(shù)內(nèi)部會通知所有的實例進行更新(就是調(diào)用每個實例的 watcher.update 方法)

具體可以看這個

響應(yīng)式原理 - 白話版
依賴更新 - 源碼版

那么我們現(xiàn)在的重點就在 watcher.update 上了,看看上面的 Watcher 代碼

出現(xiàn)了一個 queueWatcher 的東西

更新隊列

速度看源碼!

var queue = [];

var has = {};

var index = 0;

var flushing = false;

var waiting= false;



function queueWatcher(watcher) {  



    var id = watcher.id;    



    // 如果是同一個 Vue 實例,就不要重復(fù)添加了

    if (has[id] == null) {                
              

        // 這個實例已經(jīng)被標記了

        has[id] = true;        



        // 如果沒有在運行,那么直接放入隊列

        if (!flushing) {

            queue.push(watcher);
        } else {            



            // if already flushing, splice the watcher based on its id

            // if already past its id, it will be run next immediately.
            var i = queue.length - 1;            



            // 跳過所有比我大的

            while (i > index && queue[i].id > watcher.id) {
                i--;
            }  

         

            // 最后放在隊列中,一個比我老的 watcher 后面

            queue.splice(i + 1, 0, watcher);
        }        



        // 在 flushSchedulerQueue 執(zhí)行之后設(shè)置為 false

        if (!waiting) {
            waiting = true;
            nextTick(flushSchedulerQueue);
        }
    }
}

先說說其中涉及的幾個變量

has

是一個對象,用來過濾watcher。

當(dāng)這個watcher 已經(jīng)調(diào)用過更新函數(shù),那么就在 has 中標記這個 id

也就是,你同時間調(diào)用多次 watcher.update ,其實只有第一次調(diào)用有用,后面的都會被過濾掉

queue

一個數(shù)組,watcher 更新隊列,存放需要更新的 watcher

flushSchedulerQueue

watcher 更新隊列執(zhí)行函數(shù),下面有講到

waiting

為 true 表示已經(jīng)把 【watcher 更新隊列執(zhí)行函數(shù)】 注冊到宏微任務(wù)上了(或者說存放進 callbacks 中)。

正在等待JS棧為空后,就可以執(zhí)行更新。直到所有watcher 更新完畢,才重置為 false

flushing

為 true 表示 watcher 更新隊列正在執(zhí)行更新(就是開始遍歷 watcher 隊列,逐個調(diào)用 watcher 更新了)

直到所有watcher 更新完畢,才重置為 false

queueWatcher 源碼不算很復(fù)雜,主要做兩件事

1、處理watcher 更新隊列 queue

2、注冊 【watcher 更新隊列 執(zhí)行函數(shù)】進宏微任務(wù)

處理 watcher 更新隊列 queue

當(dāng) flushing 為 false時,表示 queue 還沒有開始遍歷執(zhí)行,直接 push

當(dāng) flushing 為 true,表示 queue 已經(jīng)開始遍歷,執(zhí)行其中的 watcher 更新了

然后,做了一個很特殊的插入操作(為了方便看,把上面的源碼截取了)

我還是沒有看懂這是為什么? 直到我看到了 flushSchedulerQueue 的 源碼!

因為在 flushSchedulerQueue 執(zhí)行的時候(此時設(shè)置了 flushing = true),內(nèi)部把 queue 升序排列了!

所以在 flushing 的時候,queue已經(jīng)是有序狀態(tài),中途進來的 watcher,當(dāng)然也要按順序來

所以,這一段的作用就是給 新來的 watcher 排序

其中 index 表示 現(xiàn)在正遍歷到第幾個 watcher(在 flushSchedulerQueue 中設(shè)置)

所以,也必然是排到已經(jīng)執(zhí)行過的 watcher 后面的(不然就遍歷不到這個watcher 了啊)

注冊 【watcher 更新隊列 執(zhí)行函數(shù)】進宏微任務(wù)

已經(jīng)講到 flushSchedulerQueue 了,他就是 注冊宏微任務(wù)的異步回調(diào)

直接存放進 異步任務(wù)隊列 callbacks 中的

關(guān)于 nextTick 的 異步任務(wù)隊列 ,可以看

NextTick - 源碼版 之 獨立自身

接下來,就看 flushSchedulerQueue

執(zhí)行更新隊列
function flushSchedulerQueue() {



    flushing = true;    

    var watcher;    

    

    // 升序排列

    queue.sort(function(a, b) {        

        return a.id - b.id;

    });    

    

    for (index = 0; index < queue.length; index++) {

        watcher = queue[index];
        has[watcher.id] = null;
        watcher.run();
    }    



    // 所有watcher 完成更新,重置狀態(tài)

    queue.length = 0;
    has = {};
    waiting = flushing = false;

}
flushSchedulerQueue 的作用

1、升序排列 watcher 更新隊列

2、遍歷 watcher 更新隊列,然后逐個調(diào)用 watcher 更新

3、watcher 更新隊列執(zhí)行完畢,重置狀態(tài)

其他我都看得明白,唯獨我不懂一個問題

為什么要把 queue 按照 watcher.id 升序排列??

首先,watcher.id 越大,表示這個 watcher 越年輕,實例是越后面生成的

vue 的官方回答

This ensures that:

Components are updated from parent to child. (because parent is always created before the child)

A component"s user watchers are run before its render watcher (because user watchers are created before the render watcher)

If a component is destroyed during a parent component"s watcher run, its watchers can be skipped.

我只挑一點

先更新父組件,再更新子組件(因為父組件比子組件先創(chuàng)建)

為什么先更新父組件,再更新子組件,我還是想不通啊?

個人認為,因為父組件跟子組件是有聯(lián)系的,什么聯(lián)系呢?

比如 props

當(dāng) 父組件傳給子組件的數(shù)據(jù)變化的時候,父組件需要把 變化后的數(shù)據(jù) 傳給 子組件,子組件才能知道數(shù)據(jù)變了

那么 子組件才能更新組件內(nèi)使用 props 的地方

所以,父組件必須先更新,把最新數(shù)據(jù)傳給 子組件,子組件再更新,此時才能獲取最新的數(shù)據(jù)

不然你子組件更新了,父組件再傳數(shù)據(jù)過來,那就不會子組件就不會顯示最新的數(shù)據(jù)了啊

至于 父組件更新時怎么傳 數(shù)據(jù)給子組件的?

【Vue原理】Props - 白話版

最后,走個簡單流程

數(shù)據(jù)變化,通知 watcher 更新,watcher.update

queueWatcher 把 watcher 添加進 【queue 更新隊列】

把 flushSchedulerQueue 注冊進宏微任務(wù)

JS 主棧執(zhí)行完,開始執(zhí)行異步代碼

flushSchedulerQueue 遍歷 queue ,逐個調(diào)用 watcher 更新

完成更新

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/110259.html

相關(guān)文章

  • Vue原理NextTick - 源碼 獨立自身

    摘要:盡量把所有異步代碼放在一個宏微任務(wù)中,減少消耗加快異步代碼的執(zhí)行。我們知道,如果一個異步代碼就注冊一個宏微任務(wù)的話,那么執(zhí)行完全部異步代碼肯定慢很多避免頻繁地更新。中就算我們一次性修改多次數(shù)據(jù),頁面還是只會更新一次。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5...

    劉東 評論0 收藏0
  • Vue原理NextTick - 源碼 宏微任務(wù)的抉擇

    摘要:這么講,有點籠統(tǒng),準確地說,應(yīng)該是事件回調(diào)執(zhí)行過程中,在主線程為空之后,異步代碼執(zhí)行之前,所有通過注冊的異步代碼都是用宏任務(wù)。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧 【...

    raise_yang 評論0 收藏0
  • Vue原理NextTick - 白話

    摘要:通常會做很多判斷來選擇存在的類型,比如判斷等是否存在,而選擇他為微任務(wù)類型但是可能宏微任務(wù)最后都是,因為他是保守兼容處理。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學(xué)習(xí)吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧 【V...

    zeyu 評論0 收藏0
  • 前方來報,八月最新資訊--關(guān)于vue2&3的最佳文章推薦

    摘要:哪吒別人的看法都是狗屁,你是誰只有你自己說了才算,這是爹教我的道理。哪吒去他個鳥命我命由我,不由天是魔是仙,我自己決定哪吒白白搭上一條人命,你傻不傻敖丙不傻誰和你做朋友太乙真人人是否能夠改變命運,我不曉得。我只曉得,不認命是哪吒的命。 showImg(https://segmentfault.com/img/bVbwiGL?w=900&h=378); 出處 查看github最新的Vue...

    izhuhaodev 評論0 收藏0
  • 迷你Vue--學(xué)習(xí)如何造一個Vue輪子

    摘要:項目地址和的區(qū)別其實和最大的區(qū)別就是多了一個虛擬,其他的區(qū)別都是很小的。 項目地址 Vue1和Vue2的區(qū)別 其實Vue1和Vue2最大的區(qū)別就是Vue2多了一個虛擬DOM,其他的區(qū)別都是很小的。所以理解了Vue1的源碼,就相當(dāng)于理解了Vue2,中間差了一個虛擬DOM的Diff算法 文檔 數(shù)據(jù)雙向綁定 Vue主流程走向 組件 nextTick異步更新 MVVM 先來科普一下MVVM...

    isLishude 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<