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

資訊專欄INFORMATION COLUMN

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

ityouknow / 707人閱讀

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

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

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

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

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

如果有錯誤的地方,歡迎指正哈~

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

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

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

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

getter 會在對象的這個 key 被獲取時觸發(fā),setter 會在這個對象的 key 被修改時觸發(fā)。

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

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

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

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

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

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

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

實現(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ù),從而視圖更新
實現(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()  // 通知隊列的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)式的一個基本原理,不過我描述的過程中,也省略了很多環(huán)節(jié),比如

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

為什么要進行「依賴收集」,

如何避免重復「收集依賴」

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

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

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

舉2個場景的栗子

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

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

相關(guān)文章

  • Java經(jīng)典

    摘要:請注意,我們在聊聊單元測試遇到問題多思考多查閱多驗證,方能有所得,再勤快點樂于分享,才能寫出好文章。單元測試是指對軟件中的最小可測試單元進行檢查和驗證。 JAVA容器-自問自答學HashMap 這次我和大家一起學習HashMap,HashMap我們在工作中經(jīng)常會使用,而且面試中也很頻繁會問到,因為它里面蘊含著很多知識點,可以很好的考察個人基礎(chǔ)。但一個這么重要的東西,我為什么沒有在一開始...

    xcold 評論0 收藏0
  • 利用express+socket.io實現(xiàn)一個簡易版聊天室

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

    Chaz 評論0 收藏0

發(fā)表評論

0條評論

ityouknow

|高級講師

TA的文章

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