成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

vue 源碼自問自答-響應(yīng)式原理

ityouknow / 714人閱讀

摘要:源碼自問自答響應(yīng)式原理最近看了源碼和源碼分析類的文章感覺明白了很多,但是仔細(xì)想想?yún)s說不出個(gè)所以然。會(huì)在對(duì)象的這個(gè)被獲取時(shí)觸發(fā),會(huì)在這個(gè)對(duì)象的被修改時(shí)觸發(fā)。在初始化時(shí),將對(duì)象上的所有,都包裝成擁有和的屬性。

vue 源碼自問自答-響應(yīng)式原理

最近看了 Vue 源碼和源碼分析類的文章,感覺明白了很多,但是仔細(xì)想想?yún)s說不出個(gè)所以然。

所以打算把自己掌握的知識(shí),試著組織成自己的語言表達(dá)出來

不打算平鋪直敘的寫清楚 vue 源碼的前因后果和全部細(xì)節(jié),而是以自問自答的形式,回答我自己之前的疑惑,

如果有錯(cuò)誤的地方,歡迎指正哈~

Vue 的雙向數(shù)據(jù)綁定原理

Vue 實(shí)現(xiàn)響應(yīng)式的核心 API 是 ES5 的 Object.defineProperty(obj,key,descriptor),Vue 的「響應(yīng)式」和「依賴收集」都依靠這個(gè) API

它接受 3 個(gè)參數(shù),分別是 obj / key / 描述符,返回的是一個(gè)包裝后的對(duì)象

它的作用就是,用這個(gè) API 包裝過后的對(duì)象可以擁有 getter 和 setter 函數(shù)。

getter 會(huì)在對(duì)象的這個(gè) key 被獲取時(shí)觸發(fā),setter 會(huì)在這個(gè)對(duì)象的 key 被修改時(shí)觸發(fā)。

一個(gè) Vue 項(xiàng)目的開始, 通常是從 Vue 構(gòu)造函數(shù)的實(shí)例化開始的。

new Vue()的時(shí)候會(huì)執(zhí)行一個(gè)_init()方法,會(huì)初始化屬性,比如 props/event/生命周期鉤子,也包括 data 對(duì)象的初始化。

Vue 在初始化時(shí),將 data 對(duì)象上的所有 key,都包裝成擁有 getter 和 setter 的屬性。

渲染頁面時(shí),會(huì)執(zhí)行 render function(無論是用 template 還是 render 最終都會(huì)生成 render 函數(shù))

執(zhí)行 render function 會(huì)獲取 data 對(duì)象上的屬性,所以會(huì)觸發(fā)對(duì)應(yīng)屬性的 getter 函數(shù)

getter 觸發(fā)時(shí),主要就做 2 個(gè)事情。 1.把值返回 2.依賴收集,也就是講 watcher 存放到 Dep 實(shí)例的一個(gè)隊(duì)列里。

當(dāng)修改對(duì)象的值觸發(fā) setter,setter 同樣是做 2 個(gè)事情。1.把 newVal 設(shè)置好 2.用一個(gè)循環(huán)通知之前存放在 dep 實(shí)例中 watcher 對(duì)象們,watcher 對(duì)象調(diào)用各自的 update 方法來更新視圖

實(shí)現(xiàn)雙向數(shù)據(jù)綁定的demo1 - 忽略「收集依賴」的版本
function cb() {
    console.log("更新視圖");
}

function defineReactve(obj, key, val) {
    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: () => {
            console.log("觸發(fā)了getter");
            return val;
        },
        set: newVal => {
            console.log("觸發(fā)了setter");
            if (newVal === val) return;
            val = newVal;
            cb()
        }
    });
}

function observe(data) {
    function walk(data) {
        Object.keys(data).forEach(key => {
            if (typeof data[key] === "object") {
                walk(data[key]);
            } else {
                defineReactve(data, key, data[key]);
            }
        });
    }
    walk(data);
}

class Vue {
    constructor(options) {
        this._data = options.data;
        observe(this._data);
    }
}

var vm = new Vue({
    data: {
        msg: "test",
        person: {
            name: "ziwei",
            age: 18
        }
    }
});

vm._data.person.name = "hello"

// 觸發(fā)setter和cb函數(shù),從而視圖更新
實(shí)現(xiàn)雙向數(shù)據(jù)綁定的demo2 - 「收集依賴」的版本
        function defineReactve( obj, key, val ) {
            const dep = new Dep()
            Object.defineProperty( obj, key, {
                enumerable: true,
                configurable: true,
                get: () => {
                    console.log( "觸發(fā)了getter" );
                    dep.addSub(Dep.target)
                    return val;
                },
                set: newVal => {
                    console.log( "觸發(fā)了setter" );
                    if ( newVal === val ) return;
                    val = newVal;
                    dep.notify()  // 通知隊(duì)列的wather去update視圖
                }
            } );
        }

        function observe( data ) {
            function walk( data ) {
                Object.keys( data ).forEach( key => {
                    if ( typeof data[ key ] === "object" ) {
                        walk( data[ key ] );
                    } else {
                        defineReactve( data, key, data[ key ] );
                    }
                } );
            }
            walk( data );
        }

        class Dep{
            constructor(){
                this.subs = []
            }

            addSub(){
                this.subs.push(Dep.target)
            }

            notify(){
                this.subs.forEach(sub => {
                    sub.update()
                })
            }
        }

        Dep.target = null

        class Watcher{
            constructor(){
                Dep.target = this
            }

            update(){
                console.log("update更新視圖啦~")
            }
        }

        class Vue {
            constructor( options ) {
                this._data = options.data;
                observe( this._data );

                new Watcher()           // 模擬頁面渲染,觸發(fā)getter,依賴收集的效果
                this._data.person.name
            }
        }

        var vm = new Vue( {
            data: {
                msg: "test",
                person: {
                    name: "ziwei",
                    age: 18
                }
            }
        } );

        vm._data.person.name = "hello"
一些省略掉的環(huán)節(jié)

這樣就是 Vue 響應(yīng)式的一個(gè)基本原理,不過我描述的過程中,也省略了很多環(huán)節(jié),比如

Vue 是如何實(shí)現(xiàn)給 data 對(duì)象上的屬性都擁有 getter 和 setter 的

為什么要進(jìn)行「依賴收集」,

如何避免重復(fù)「收集依賴」

watcher 調(diào)用 update,也并不是直接更新視圖。實(shí)現(xiàn)上中間還有 patch 的過程以及使用隊(duì)列來異步更新的策略。

Vue 是如何實(shí)現(xiàn)給 data 對(duì)象上的屬性都擁有 getter 和 setter 的
通過循環(huán)data對(duì)象,給對(duì)象的每一個(gè)key,用Object.defineProperty包裝

遍歷時(shí),如果發(fā)現(xiàn)data[key]也是對(duì)象的話,需要用遞歸
為什么要進(jìn)行「依賴收集」?

舉2個(gè)場(chǎng)景的栗子

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98913.html

相關(guān)文章

  • Java經(jīng)典

    摘要:請(qǐng)注意,我們?cè)诹牧膯卧獪y(cè)試遇到問題多思考多查閱多驗(yàn)證,方能有所得,再勤快點(diǎn)樂于分享,才能寫出好文章。單元測(cè)試是指對(duì)軟件中的最小可測(cè)試單元進(jìn)行檢查和驗(yàn)證。 JAVA容器-自問自答學(xué)HashMap 這次我和大家一起學(xué)習(xí)HashMap,HashMap我們?cè)诠ぷ髦薪?jīng)常會(huì)使用,而且面試中也很頻繁會(huì)問到,因?yàn)樗锩嫣N(yùn)含著很多知識(shí)點(diǎn),可以很好的考察個(gè)人基礎(chǔ)。但一個(gè)這么重要的東西,我為什么沒有在一開始...

    xcold 評(píng)論0 收藏0
  • 利用express+socket.io實(shí)現(xiàn)一個(gè)簡(jiǎn)易版聊天室

    摘要:用偽代碼來模擬下長(zhǎng)輪詢的過程前端利用下面函數(shù)進(jìn)行請(qǐng)求后端代碼做如下更改利用隨機(jī)數(shù)的大小來模擬是否有新數(shù)據(jù)有新數(shù)據(jù)來了長(zhǎng)輪詢的確減少了請(qǐng)求的次數(shù),但是它也有著很大的問題,那就是耗費(fèi)服務(wù)器的資源。 寫在前面 最近由于利用node重構(gòu)某個(gè)項(xiàng)目,項(xiàng)目中有一個(gè)實(shí)時(shí)聊天的功能,于是就研究了一下聊天室,在線demo|源碼,歡迎大家反饋。這個(gè)聊天室的主要利用到了socket.io和express。這個(gè)...

    Chaz 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

ityouknow

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<