亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

【Vue原理】Watch - 源碼版

Hancock_Xu / 1581人閱讀

摘要:寫文章不容易,點個贊唄兄弟專注源碼分享,文章分為白話版和源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于版本如果你覺得排版難看,請點擊下面鏈接或者拉到下面關(guān)注公眾號也可以吧原理源碼版今天繼續(xù)探索源碼,廢話不

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

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

【Vue原理】Watch - 源碼版

今天繼續(xù)探索 Watch 源碼,廢話不多說了

帶著我的幾個疑問開始

1、什么時候初始化

2、怎么確定監(jiān)聽哪些值

3、深度監(jiān)聽怎么回事

4、怎么觸發(fā)我的函數(shù)

這些問題的答案會摻雜在源碼的解析中,我發(fā)現(xiàn)這幾篇的寫作套路都差不多.....

也可以看查一下我的白話版

什么時候初始化

首先,從這個問題開始我們今天的探索之旅,請看源碼

function Vue(){
    ... 其他處理
    initState(this)

    ...解析模板,生成DOM 插入頁面

}



function initState(vm) {


    ...處理 data,props,computed 等數(shù)據(jù)

    if (opts.watch) {
        initWatch(this, vm.$options.watch);
    }
}

沒錯,當你調(diào)用 Vue 創(chuàng)建實例過程中,會去處理各種選項,其中包括處理 watch

initWatch

處理 watch的方法是 initWatch,下面就呈上 源碼

function initWatch(vm, watch) {    

    for (var key in watch) {    

        var watchOpt = watch[key];
        createWatcher(vm, key, handler);
    }
}

然后這段源碼并沒有做什么驚天地泣鬼神的事情,只是簡簡單單的一個遍歷,然后每個watch 都使用一個叫什么 createWatcher 的東西去處理

這個函數(shù)到底是干嘛的?暗藏著什么秘密,歡迎來到我們今晚的 《走近科學》《源碼解析》

createWatcher 來看看他的真身

function createWatcher(
    // expOrFn 是 key,handler 可能是對象
    vm, expOrFn, handler,opts

) {    

    // 監(jiān)聽屬性的值是一個對象,包含handler,deep,immediate

    if (typeof handler ==="object") {
        opts= handler
        handler = handler.handler
    }    



    // 回調(diào)函數(shù)是一個字符串,從 vm 獲取

    if (typeof handler === "string") {
        handler = vm[handler]
    }    



    // expOrFn 是 key,options 是watch 的全部選項

    vm.$watch(expOrFn, handler, opts)
}

大概就這樣吧

1、獲取到監(jiān)聽回調(diào)

2、調(diào)用 vm.$watch

1、獲取監(jiān)聽回調(diào)

首先,你傳入的 watch 配置可能是這三種(還有更多,差不多,不解釋,累死我)

如果配置是個對象,就取handler 字段

如果配置是函數(shù),那么直接就是 監(jiān)聽回調(diào)

如果配置是字符串,從實例上獲取函數(shù)

2、調(diào)用 vm.$watch

看著這個方法,簡直 mmp,還有完沒完,我從一個函數(shù)進入一個函數(shù),又從這個函數(shù)進入到另一個函數(shù),迷宮啊這是.....

顯然你不用急,下面還有更多......

好吧,還是先看源碼

Vue.prototype.$watch = function(
    // expOrFn 是 監(jiān)聽的 key,cb 是監(jiān)聽回調(diào),opts 是所有選項

    expOrFn, cb, opts

){    

    // expOrFn 是 監(jiān)聽的 key,cb 是監(jiān)聽的回調(diào),opts 是 監(jiān)聽的所有選項

    var watcher = new Watcher(this, expOrFn, cb, opts);    



    // 設(shè)定了立即執(zhí)行,所以馬上執(zhí)行回調(diào)

    if (opts.immediate) {
        cb.call(this, watcher.value);
    }
};

看完了吧?這么短,你們肯定看得懂的啦,就兩件事

1、判斷是否立即執(zhí)行監(jiān)聽回調(diào)

如果你設(shè)置了 immediate 的話,表示不用等我數(shù)據(jù)變化,初始化時馬上執(zhí)行一遍,執(zhí)行的代碼就是直接調(diào)用 回調(diào),綁定上下文,傳入監(jiān)聽值

2、每個 watch 配發(fā) watcher

代碼從這里開始變得沉重,各位觀眾,喝口水,恰口飯,屏息觀看操作

看看 watcher 的源碼

“watcher 的源碼之前的文章也講過很多,但是對于每種選項的涉及的細節(jié)是不一樣的,所以每次都放上來,但是只放跟本內(nèi)容相關(guān)的部分代碼,其他的省去以便我們快速理解”

var Watcher = function (vm, key, cb, opt) {  

    this.vm = vm;    

    this.deep = opt.deep;    

    this.cb = cb;  

    // 這里省略處理 xx.xx.xx 這種較復(fù)雜的key
    this.getter = function(obj) {        

        return obj[key]

    };    

    // this.get 作用就是執(zhí)行 this.getter函數(shù)

    this.value = this.get();
};

再看看,新建 watcher 的時候 ,傳入了什么

1、監(jiān)聽的 key

2、監(jiān)聽回調(diào) (Watch 中的cb)

3、監(jiān)聽配置的options

這里會涉及到三個問題,現(xiàn)在來解釋

1、怎么對設(shè)置的 key 進行監(jiān)聽?

我們要先對 Watch 中的 this.getter 的函數(shù)進行理解,他的本質(zhì)是為了獲取對象的key值

然后 getter 是在 watcher.get 中執(zhí)行的,看下 get 源碼

// 對本問題進行了獨家簡單化的源碼

Watcher.prototype.get = function() {    

    var value = this.getter(this.vm);    

    return value

};

你能看到,Watch 在結(jié)尾會立即執(zhí)行一次 watcher.get,其中便會執(zhí)行 getter,便會根據(jù)你監(jiān)聽的key,去實例上讀取并返回,存放在 watcher.value 上

看到了嗎,從實例上讀取屬性,這句話。

首先,watch 初始化之前,data 應(yīng)該初始化完畢了,每個 data 數(shù)據(jù)都已經(jīng)是響應(yīng)式的

使用例子來說明一下

當 watch.getter 執(zhí)行,而讀取了 vm.name 的時候,name的依賴收集器就會收集到 watch-watcher

于是 name 變化的時候,會可以通知到 watch,監(jiān)聽就成功了

2、如何進行深度監(jiān)聽?

首先,深度監(jiān)聽,是你設(shè)置了 deep 的時候,如下

然后,觀察上面的 Watch 源碼,deep 會保存在watcher 中,以便后用

話鋒一轉(zhuǎn)

上一問題說過,在 新建 watcher 的時候,會馬上執(zhí)行一個 get,上個問題的 get 源碼簡化很多,把 處理深度監(jiān)聽的部分去掉了,這里露出來了

Watcher.prototype.get = function() {
    Dep.target= this

    var value = this.getter(this.vm)    

    if (this.deep)  traverse(value)

    Dep.target= null
    return value
};

沒錯,處理深度監(jiān)聽只有一條語句!

if (this.deep)  traverse(value)

value 是 getter 從實例上讀取監(jiān)聽key 得到的值,沒有疑問

但是 traverse 是何方神圣?come on 讓我們深入....

function traverse(val) {    

    var i, keys;    



    // 數(shù)組逐個遍歷

    if (Array.isArray(val)) {

        i = val.length;        

        // val[i] 就是讀取值了,然后值的對象就能收集到 watch-watcher

        while (i--) {
           traverse(val[i])
        }
    }    

    else {

        keys = Object.keys(val);
        i = keys.length;        

        // val[keys[i]] 就是讀取值了,然后值的對象就能收集到 watch-watcher

        while (i--) {
           traverse(val[keys[i]])
        }
    }
}

你看它這段代碼長,其實是個紙老虎,做的就是一個事情,不斷遞歸深入讀取對象

他的想法是這樣的

因為讀取,就可以讓這個屬性收集到 watch-watcher 的原則

就算是深層級的對象,其中的每個屬性也都是響應(yīng)式的,每個屬性都有自己的依賴收集器

通過不斷深入的讀取每個屬性,這樣每個屬性就都可以收集到 watch-watcher 了

這樣不管對象內(nèi)多深的屬性變化,都會通知到 watch-watcher

于是這樣就完成了深度監(jiān)聽

3、監(jiān)聽值變化,如何觸發(fā)監(jiān)聽函數(shù)?

通過上面的問題,我們已經(jīng)了解了大部分了

監(jiān)聽的數(shù)據(jù)變化的時候,就能通知 watch-watcher 更新,所謂通知更新,就是手動調(diào)用 watch.update

速度看下 watcher.update 源碼

Watcher.prototype.update= function() {    

    var value = this.get();    

    if (this.deep) {        

        var oldValue = this.value;        

        this.value = value;        

        // cb 是監(jiān)聽回調(diào)
        this.cb.call(this.vm, value, oldValue);
    }
};

很簡單嘛,就是讀取一遍值,然后保存新值,接著 調(diào)用 監(jiān)聽回調(diào),并傳入新值和 舊值

ok,就這樣

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/105380.html

相關(guān)文章

  • Vue原理Watch - 白話

    摘要:而是在初始化時,在讀取了監(jiān)聽的數(shù)據(jù)的值之后,便立即調(diào)用一遍你設(shè)置的監(jiān)聽回調(diào),然后傳入剛讀取的值設(shè)置了時,如何工作我們都知道有一個選項,是用來深度監(jiān)聽的。 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下...

    hzx 評論0 收藏0
  • Vue原理】Mixins - 源碼

    寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧 【Vue原理】Mixins - 源碼版 今天探索的是 mixins 的源碼,mixins 根據(jù)不同的選項類型會做不同的處理 篇幅會有些長,...

    gotham 評論0 收藏0
  • Vue原理】Mixin - 白話

    摘要:而我覺得現(xiàn)在出一個白話版,是讓大家有興趣去研究源碼的時候,可以提前理清一下思路。相當于封裝,提取公共部分。顯然,今天我不是來教大家怎么用的,怎么用看文檔就好了,我是講解生命的真諦內(nèi)部的工作原理。而這個不會合并,直接替換掉整個選項 寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于 Vue版...

    CollinPeng 評論0 收藏0
  • Vue原理】Props - 源碼

    寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧 【Vue原理】Props - 源碼版 今天記錄 Props 源碼流程,哎,這東西,就算是研究過了,也真是會隨著時間慢慢忘記的。 幸好我做...

    light 評論0 收藏0
  • Vue原理】NextTick - 源碼 之 服務(wù)Vue

    寫文章不容易,點個贊唄兄弟專注 Vue 源碼分享,文章分為白話版和 源碼版,白話版助于理解工作原理,源碼版助于了解內(nèi)部詳情,讓我們一起學習吧研究基于 Vue版本 【2.5.17】 如果你覺得排版難看,請點擊 下面鏈接 或者 拉到 下面關(guān)注公眾號也可以吧 【Vue原理】NextTick - 源碼版 之 服務(wù)Vue 初次看的兄弟可以先看 【Vue原理】NextTick - 白話版 簡單了解下...

    Acceml 評論0 收藏0

發(fā)表評論

0條評論

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