亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

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

JS源碼分析│簡易mvvm庫的設計實現

發布時間:2020-07-04 19:13:03 來源:網絡 閱讀:183 作者:數瀾 欄目:大數據

作者:刀哥(朱建)

前言:mvvm模式即model-view-viewmodel模式簡稱,單項/雙向數據綁定的實現,讓前端開發者們從繁雜的dom事件中解脫出來,很方便的處理數據和ui之間的聯動。本文將從vue的雙向數據綁定入手,剖析mvvm庫設計的核心代碼與思路。

1、需求整理與分析

需求:

  • 數據一旦改變則更新數據對應的ui

  • ui改變則觸發事件改變ui對應的數據

分析:

  • 通過dom節點的指令獲取刷新函數,用來刷新指定的ui。

  • 實現一個橋接的方法,讓刷新函數和需要的數據關聯起來。

  • 監聽數據變化,數據改變后通過橋接方法調用刷新函數。

  • ui改變觸發對應的dom事件在改變特定的數據。

2、實現思路

  • 實現observer,重新定義data,為data上每個屬性增加setter,getter以監聽數據的變化。

  • 實現compile,掃描模版template,提取每個dom節點中的指令信息。

  • 實現directive,通過指令信息是實例化對應的directive實例,不同類型的directive擁有不同的刷新函數update。

  • 實現watcher,讓observer的屬性監聽函數與directive的update函數做一一對應,以實現數據變化后更新視圖。

3、模塊劃分

MVVM目前劃分為observer,compile,directive,watcher四個模塊。

4、數據監聽模塊observer

通過es5規范中的object.defineProperty方式實現對數據的監聽。

5、實現思路

遞歸遍歷data,將data下面所有屬性都加上set,get方法,以實現對所有屬性的攔截.

注意:對象可能含有數組屬性,數組的內置有push,pop,splice等方法改變內部數據.

此時做法是改變數組的原型鏈,在原型鏈中增加一層自定義的push,pop,splice方法做攔截,這些方法里面加上我們自己的回調函數,然后在調用原生的push,pop,splice等方法。

export function defineProperty(obj, prop, val) {
if (prop == '__observe__') {

    return;

}

val = val || obj[prop];

var dep = new Dep();

obj.__observe__ = dep;

var childDep = addObserve(val);

Object.defineProperty(obj, prop, {

    get: function() {

        var target = Dep.target;

        if (target) {

            dep.addSub(target);

            if (childDep) {

                childDep.addSub(target);

            }

        }

        return val;

    },

    set: function(newVal) {

        if(newVal!=val){

            val = newVal;

            dep.notify();

        }

    }

});
}

6、編譯模塊compiler

實現思路:

  • 將模版template上的dom遍歷一遍,將其存入文檔碎片frag

  • 遍歷frag,通過attributes獲取節點的屬性信息,在通過正則表達式過濾屬性信息,進而拿到元素節點和文檔節點的指令信息
var complieTemplate = function (nodes, model) {

if ((nodes.nodeType == 1 || nodes.nodeType == 11) && !isScript(nodes)) {
paserNode(model, nodes);

if (nodes.hasChildNodes()) {

  nodes.childNodes.forEach(node=> {

    complieTemplate(node, model);

  })

}
}

};

7、指令模塊directive

指令信息如:v-text,v-for,v-model等。

每種指令信息需要的初始化動作以及指令的刷新函數update都可能不一樣,所以我們把它抽象出來單獨做一個模塊。當然也有公用的如公共屬性,統一的watcher實例化,unbind.

update函數則具體定義所屬指令如何渲染ui,如簡單的vtext指令的update函數如下:

vt.update = function (textContent) {
this.el.textContent = textContent;
};

9、結構圖

JS源碼分析│簡易mvvm庫的設計實現cdn.xitu.io/2019/9/3/16cf5cc170b0c95d?w=640&h=522&f=png&s=22778">)

9、數據訂閱模塊watcher

watcher的功能是讓directive和observer模塊關聯起來。初始化的時候做兩件事:

  • 將directive模塊的update函數當參數傳入,并將其存入自身update屬性中。

  • 調用getValue,從而獲取對象data的特定屬性值,進而觸發一次之前在observer定義的屬性函數的getter方法。

由于在defineProperty函數中定義的dep變量在setter和getter函數里有引用,使dep變量處于閉包狀態沒有釋放,此時在getter方法中通過判斷Depend.target的存在,來獲取訂閱者watcher,通過發布者dep儲存起來。數據的每個屬性都有一個唯一的的dep變量,記錄著所有訂閱者watcher的信息,一旦屬性有變化,調用setter函數的時候觸發dep.notify(),通知所有已訂閱的watcher,進而執行所有與該屬性關聯的刷新函數,最后更新指定的ui。

watcher 初始化部分代碼:

Depend.target = this;

this.value = this.getValue();

Depend.target = null;

observer.js 屬性定義代碼:

export function defineProperty(obj, prop, val) {
if (prop == '__observe__') {

    return;

}

val = val || obj[prop];

var dep = new Dep();

obj.__observe__ = dep;

var childDep = addObserve(val);

Object.defineProperty(obj, prop, {

    get: function() {

        var target = Dep.target;

        if (target) {

            dep.addSub(target);

            if (childDep) {

                childDep.addSub(target);

            }

        }

        return val;

    },

    set: function(newVal) {

        if(newVal!=val){

            val = newVal;

            dep.notify();

        }

    }

});
}

10、流程圖

JS源碼分析│簡易mvvm庫的設計實現

11、總結

文基本對mvvm庫的需求整理,拆分,以及對拆分模塊的逐一實現來達到整體雙向綁定功能的實現,當然目前市場上的mvvm庫功能絕不止于此,本文只是略舉個人認為的核心代碼。如果思路和實現上的問題,也請各位斧正,謝謝閱讀!

原代碼:https://github.com/laughing-pic-zhu/mvvm

想要深入了解的同學可以訪問數瀾社區,和大家一起討論學習~

向AI問一下細節

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

AI

恭城| 县级市| 张家界市| 应城市| 广宁县| 荆州市| 高雄县| 龙州县| 唐河县| 泾阳县| 杭州市| 衡阳县| 武定县| 丰顺县| 通渭县| 图木舒克市| 启东市| 辽阳县| 齐齐哈尔市| 潍坊市| 兴国县| 岳西县| 海林市| 乡宁县| 荃湾区| 南部县| 古田县| 白城市| 峨山| 措美县| 宁远县| 横峰县| 丰台区| 镇巴县| 东乌珠穆沁旗| 黑龙江省| 太原市| 应城市| 姚安县| 紫云| 金坛市|