摘要:這段代碼出現在解析屬性的時候,即調用方法配置的屬性。最終是周知訂閱者更新,那么上面的數據變更就是發布者。在指令中實例化了,函數負責來更新在解析模板的時候會解析,然后綁定,實例化,這樣模板就關聯在一起了。
本文地址: http://www.iamaddy.net/2016/1...
一說到監聽,當然就離不了設計模式中鼎鼎大名的觀察者模式。舉個例子,你家后院著火了,可一定要等到煙霧很大火光很亮你才能發現啊,可是當你安裝了一個火災預警器,當發生火災就立馬能夠通知到你了。這就是一個典型的觀察者模式。當然也還有一些其他變種,比如發布/訂閱(publish/subscribe)模式。
我們知道如果要將數據和視圖關聯起來,在數據變更的時候,同步視圖,同理視圖變更,數據也發生變化。vue.js是怎么實現這個的呢?下面我們來揭開它的神秘面紗。
demo:
{{ message }}
set: function reactiveSetter(newVal) { var value = getter ? getter.call(obj) : val; if (newVal === value) { return; } if (setter) { setter.call(obj, newVal); } else { val = newVal; } childOb = observe(newVal); dep.notify(); }
這段代碼出現在解析data屬性的時候,即調用Object.defineProperty方法配置data的屬性。一旦屬性發生變化,就notify發送廣播。
Dep.prototype.notify = function () { // stablize the subscriber list first var subs = toArray(this.subs); for (var i = 0, l = subs.length; i < l; i++) { subs[i].update(); } };
notify 最終是周知subscribe(訂閱者)更新,那么上面的數據變更就是發布者。
subscribe是Watcher這個類的實例化對象,在實例化的時候,會傳入回調函數來執行update,vue弄了一個隊列來執行watcher的更新函數,具體可參考源碼。
Watcher.prototype.run = function () { …… if (value !== this.value || (isObject(value) || this.deep) && !this.shallow) { …… } else { this.cb.call(this.vm, value, oldValue); } } this.queued = this.shallow = false; } };
在Directive(指令)class中實例化了Watcher,_update函數負責來更新
var watcher = this._watcher = new Watcher(this.vm, this.expression, this._update, // callback { filters: this.filters, twoWay: this.twoWay, deep: this.deep, preProcess: preProcess, postProcess: postProcess, scope: this._scope });
在解析模板的時候會解析Directive,然后綁定,實例化watcher,這樣模板-data就關聯在一起了。
林林總總的mvc或者mvvm框架基本也都是利用了觀察者模式,這個也非常有用,尤其在復雜的系統之中。
利用觀察者模式,在典型的ajax應用中,回調的處理邏輯可以不跟請求耦合在一塊,這樣邏輯上也會更加清晰。如下是一個簡單的發布/訂閱模式的實現
var PubSub = {}; (function (q) { var topics = {}, subUid = -1; q.publish = function (topic) { if(!topics[topic]){ return false; } var subscribers = topics[topic], len = subscribers ? subscribers.length : 0; while(len--){ var args = Array.prototype.slice.call(arguments, 1); args.unshift(topic); subscribers[len].callback.apply(this, args); } return this; }; q.subscribe = function (topic, callback) { if(!topics[topic]){ topics[topic] = []; } var subuid = (++subUid).toString(); topics[topic].push({ token: subuid, callback: callback }); return subuid; }; q.unsubscribe = function (subid) { for(var k in topics){ if(topics[k]){ for(var i = 0, j = topics[k].length; i < j; i++){ if(topics[k][i].token === subid){ topics[k].splice(i, 1); return subid; } } } } return this; }; })(PubSub);
這就是一個簡單的訂閱發布系統,每注冊一個訂閱者,其實就是將其回調處理的callback保存在一個字典對象的數組中,字典對象的key值可以隨意定義,只要與發布時的key對應起來就好。怎么使用呢?
最后一個將不會打印出來,因為已經取消訂閱了。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/87764.html
摘要:實際上,我在看代碼的過程中順手提交了這個,作者眼明手快,當天就進行了修復,現在最新的代碼里已經不是這個樣子了而且狀態機標識由字符串換成了數字常量,解析更準確的同時執行效率也會更高。 最近饒有興致的又把最新版?Vue.js?的源碼學習了一下,覺得真心不錯,個人覺得 Vue.js 的代碼非常之優雅而且精辟,作者本身可能無 (bu) 意 (xie) 提及這些。那么,就讓我來吧:) 程序結構梳...
摘要:實際上,我在看代碼的過程中順手提交了這個,作者眼明手快,當天就進行了修復,現在最新的代碼里已經不是這個樣子了而且狀態機標識由字符串換成了數字常量,解析更準確的同時執行效率也會更高。 最近饒有興致的又把最新版?Vue.js?的源碼學習了一下,覺得真心不錯,個人覺得 Vue.js 的代碼非常之優雅而且精辟,作者本身可能無 (bu) 意 (xie) 提及這些。那么,就讓我來吧:) 程序結構梳...
摘要:假如你通過閱讀源碼,掌握了對的實現原理,對生態系統有了充分的認識,那你會在面試環節游刃有余,達到晉級阿里的技術功底,從而提高個人競爭力,面試加分更容易拿。 前言 一年一度緊張刺激的高考開始了,與此同時,我也沒閑著,奔走在各大公司的前端面試環節,不斷積累著經驗,一路升級打怪。 最近兩年,太原作為一個準二線城市,各大互聯網公司的技術棧也在升級換代,假如你在太原面試前端崗位,而你的技術庫里若...
摘要:當我們的視圖和數據任何一方發生變化的時候,我們希望能夠通知對方也更新,這就是所謂的數據雙向綁定。返回值返回傳入函數的對象,即第一個參數該方法重點是描述,對象里目前存在的屬性描述符有兩種主要形式數據描述符和存取描述符。 前言 談起當前前端最熱門的 js 框架,必少不了 Vue、React、Angular,對于大多數人來說,我們更多的是在使用框架,對于框架解決痛點背后使用的基本原理往往關注...
閱讀 2379·2023-04-25 20:07
閱讀 3314·2021-11-25 09:43
閱讀 3674·2021-11-16 11:44
閱讀 2539·2021-11-08 13:14
閱讀 3187·2021-10-19 11:46
閱讀 905·2021-09-28 09:36
閱讀 3000·2021-09-22 10:56
閱讀 2383·2021-09-10 10:51