前言:最近團隊需要做一個分享,腳進腦子,不知如何分享。最后想著之前一直想研究一下 vue 源碼,今天剛好 “借此機會” 研究一下。
網上研究vue數據綁定的文章已經非常多了,但是自己寫一遍,敲一遍demo和看別人的文章是完全不同的,so……搬運工來了
目前數據綁定主要有以下三種實現方式:
1. 臟值檢查(angular.js) 輪詢檢測數據變化
DOM事件,譬如用戶輸入文本,點擊按鈕等。( ng-click )
2、Object.defineProperty劫持對象的get、set,從而實現對數據的監控。 (vue)
3、發布/訂閱者模式實現數據與視圖的自動同步
Object.defineProperty的優點
Object.defineProperty的用法
var a = {};?Object.defineProperty(a, "b", {? set: function (newValue) {? console.log("我被賦值了!" + newValue);? },? get: function () {? console.log("我被取值了!");? return 2 }?})?a.b = 3; //我被賦值了!?console.log(a.b); //我被取值了! //打印 2由上面的例子看出,Object.defineProperty 傳人3個參數
第一個: a對象
第二個: a對象里面的b屬性
第三個: 屬性比較多,列舉有用的 value,set,get,configurable
數據綁定原理:
1、實現一個數據監聽器Observer,對數據對象的所有屬性進行監聽,如有變動則拿到最新值并通知 dep數組
2、實現一個指令解析器Compile,對每個元素節點的指令進行掃描和解析,根據指令模板替換數據
3、實現一個dep數組 ,能夠訂閱并收到每個屬性變動的通知,執行指令綁定的相應回調函數,更新視圖
1. 實現observer
var data = {name: 'beidan'};?observe(data);?data.name = 'test'; // 監聽到值變化了 beidan 變成 test??function observe(data) {? if (!data || typeof data !== 'object') {? return;? }? // 取出所有屬性遍歷? Object.keys(data).forEach(function(key) {? defineReactive(data, key, data[key]);? });}function defineReactive(data, key, val) {?? Object.defineProperty(data, key, {? enumerable: true, // 可枚舉? configurable: false, // 不能再define get: function() {? return val;? },? set: function(newVal) {? console.log('監聽到值變化了 ', val, ' 變成 ', newVal);? val = newVal;? }? });}2. 維護一個數組
function Dep() {? this.subs = [];}?Dep.prototype = {? addSub: function (sub) {? this.subs.push(sub);? },? notify: function (val) {? this.subs.forEach(function (sub) {? sub.update(val)? });? }?};function defineReactive(data, key, val) { Object.defineProperty(data, key, { …… set: function(newVal) { if (val === newVal) return; console.log('監聽到值變化了 ', val, ' 變成 ', newVal); val = newVal; dep.notify(val); // 通知所有訂閱者 } });}3. compile
bindText: function () {? var textDOMs = this.el.querySelectorAll('[v-text]'),?bindText,_context = this;?? for (var i = 0; i < textDOMs.length; i++) {? bindText = textDOMs[i].getAttribute('v-text'); textDOMs[i].innerHTML = this.data[bindText];? var val = textDOMs[i]?? var up = function (text) {? val.innerText = text? }? _context.dep.addSub({? value: textDOMs[i],? update: up? });? }?},最后,附上源碼 github https://github.com/beidan/vue_bind
以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持VeVb武林網!
新聞熱點
疑難解答