之前每件事都差不多,直到現在才發現差很多。ps: 文章略長。現在才發現理清一件事的原委是多麼快樂的一件事,我們共同勉勵。
紙上得來終覺淺,絕知此事要躬行
懶得扯淡,直接正題
model
->view
編譯器
其基於 訂閱者-發布者模式,簡單的講就是訂閱者訂閱資料,一旦訂閱的資料變更過後,更新繫結的view檢視。
這裡有明確的分工,分別是***、發布器和訂閱器,這3者相互協作,各司其職。
過2s資料更改,更新到檢視
顧名思義,***,***,監聽的就是資料的變化
建立需要解決訂閱者的新增和發布器通知訂閱器的時機發布器;發布器 新增
訂閱器;
發布器 通知
訂閱器
object.difineproperty為我們提供了方便,其語法如下:
var obj = {};
object.defineproperty(obj, 'a', );
console.log(obj.a); // 輸出a
definepropery
除了可以定義數值以外,還可以定義 get 和 set 訪問器,如下:
var obj = {};
var value = 'a';
object.defineproperty(obj, 'a', ,
set: function (val)
});console.log(obj.a);
obj.a = 'b';
console.log(obj.a);
執行結果如下所示:
資料的變化無非就是讀和寫,由此,我們可以得出訂閱器的新增和發布器通知訂閱器
的時機,就是屬性值的獲取和重置。
function observe(data)
object.keys(data).foreach((val, key) => )
}function definereactive(data, key, val) ,值為$`);
return val;
},set: function (newvalue) ,變為$`);
val = newvalue;
}});
}var obj =
}observe(obj);
新增訂閱器;通知
訂閱器
function dep ()
dep.prototype.addsub = function(sub);
dep.prototype.notify = function());
};
發布器**寫好了,我們再重新修改一下*****。主要修改點為:新增訂閱器和發布器通知訂閱器
function definereactive(data, key, val) ,值為$`);
+ dep.addsub();
return val;
},set: function (newvalue) ,變為$`);
val = newvalue;
}
更新檢視
function watcher (vm, key, cb)
watcher.prototype.update = function()
};watcher.prototype.get = function();
訂閱器**寫好了,我們再重新修改一下*****。主要修改點為:如何新增訂閱器
enumerable: true,
configurable: true,
get: function ()
return val;
},set: function (newvalue) );
}
var vm = new vue(, document.getelementbyid('root'), 'name');
settimeout(() => , 2000);
還有一點,通常資料的變更是直接使用vm.name,而非vm.data.name,其實也很簡單,直接使用**,vm.name讀取和寫都**到vm.data.name上即可。
+ var self = this;
+ object.keys(this.data).foreach(function(property, index) );
+ var watcher = new watcher(this, key, function (name) );
-}+}
++vue.prototype.proxyproperty = function(property),
+ set: function (value)
+ });
+};
詳細**參考github專案
$ git clone
$ cd vue-like
$ git checkout model2view
上面的例項看起來,有點問題,我們是寫死監聽的資料,然後修改dom上的innerhtml,實際中,肯定不會這樣,需要在dom中繫結資料,然後動態監聽資料變化。
首先需要明確編譯器
有哪些工作需要做
檢視繫結資料,2s後資料更新,更新到檢視
對dom結構的解析這裡使用文件片段
,其dom操作效能優於其他。
function compile (options, vm)
compile.prototype.createelement = function (ele)
return fragment;
}compile.prototype.compileelement = function (el) \}/;
var text = node.textcontent;
if (reg.test(text))
if (node.childnodes && node.childnodes.length > 0)
});}compile.prototype.compiletext = function (node, key) );
}compile.prototype.updatetext = function (node, text)
compile.prototype.viewrefresh = function();
詳細**參考github專案
$ git clone
$ cd vue-like
$ git checkout compile
這個比較簡單,在compile 解析時,判斷是否是元素節點,如果元素節點中包含指令v-model
,從中讀取監聽的資料屬性,再從 model中讀取,除此以外還要繫結乙個input事件,用於view -> model
詳細**參考github專案
詳細**參考github專案
$ git clone
$ cd vue-like
$ git checkout event
比如說建立、初始化、更新、銷毀等。
詳細**參考github專案
$ git clone
$ cd vue-like
$ git checkout lifecircle
vue實現雙向資料繫結
object.defineproperty 方法會直接在乙個物件上定義乙個新屬性,或者修改乙個物件的現有屬性,並返回這個物件。object.defineproperty 方法有三個引數 引數 功能 作用 obj 要修改或定義key值的物件 key 對應obj物件的裡面某有已有或要修改的屬性 opti...
Vue如何實現資料雙向繫結
說明 index.html lang en head p p v text msg p v text car.color p v html msg p v html car.color p type text v model msg v on click clickfn 點我button div...
vue實現資料雙向繫結原理
vue實現資料雙向繫結主要是採用資料劫持結合發布者 訂閱者的模式的方式來實現。通過object.defineproperty 的get和set來劫持每個屬性,在資料發生變化時通過發布者發訊息給訂閱者,觸發相應的監聽回掉。具體就是先把說有的資料做乙個資料劫持。第一先修改資料,在input框輸入值的時候...