摘要:在此種模式中,一個目標對象管理所有相依于它的觀察者對象,并且在它本身的狀態改變時主動發出通知。訂閱者模式涉及三個對象發布者主題對象訂閱者,三個對象間的是一對多的關系,每當主題對象狀態發生改變時,其相關依賴對象都會得到通知,并被自動更新。
1./compiler ?目錄是編譯模版;
2./core ?目錄是 Vue.js 的核?心(也是后?面的重點);
3./platforms ?目錄是針對核?心模塊的 ‘平臺’ 模塊;
4./server ?目錄是處理理服務端渲染;
5./sfc ?目錄處理理單?文件 .vue;
6./shared ?目錄提供全局?用到的?工具函數。
Vue.js 的組成是由 core + 對應的 ‘平臺’ 補充代碼構成(獨立構建和運行時構建 只是 platforms 下 web 平臺的兩種選擇)。
雙向綁定(響應式原理)所涉及到的技術
1. Object.defineProperty 2. Observer 3. Watcher 4. Dep 5. Directive1. Object.defineProperty
var obj = {};
var a;
Object.defineProperty(obj,"a",{
get: function(){
console.log("get val");
return a;
},
set: function(newVal){
console.log("set val:" + newVal);
a = newVal;
}
});
obj.a // get val; 相當于{{a}}
obj.a = "111"; // set val:111 相當于
setter 觸發消息到 Watcher watcher幫忙告訴 Directive 更新DOM,DOM中修改了數據 也會通知給 Watcher,watcher 幫忙修改數據。
觀察者模式是軟件設計模式的一種。 在此種模式中,一個目標對象管理所有相依于它的觀 察者對象,并且在它本身的狀態改變時主動發出通知。 這通常透過呼叫各觀察者所提供的 方法來實現。此種模式通常被用來實時事件處理系統。 訂閱者模式涉及三個對象: 發布者、主題對象、訂閱者,三個對象間的是一對多的關系, 每當主題對象狀態發生改變時,其相關依賴對象都會得到通知,并被自動更新。 看一個簡單的示例:
vue里邊怎么操作的呢? vue observer
watcher
Dep
Directive
弄明白原理和架構之后,我們來實現一個簡單的vue雙向數據綁定
1.這個Vue是從哪里來的呢?
是通過上述方法實例化的一個對象;但是里邊有兩個未知生物 observe ? Compile?
observe中寫的是雙向綁定的核心原理就是Object.defineProperty
通過set,get來設置值與獲取值
把text屬性綁定到vue實例上面去使用
那其中的Dep又是什么呢?
添加訂閱者跟通知訂閱更新
再來看一下Compile中寫的什么吧
function Compile(node, vm) { if (node) { this.$frag = this.nodeToFragment(node, vm); return this.$frag; } } Compile.prototype = { nodeToFragment: function (node, vm) { var self = this; var frag = document.createDocumentFragment(); // 創建一段html文檔片段 var child; while (child = node.firstChild) { self.compileElement(child, vm); frag.append(child); // 將所有子節點添加到fragment中 } return frag; }, compileElement: function (node, vm) { var reg = /{{(.*)}}/; //節點類型為元素 if (node.nodeType === 1) { var attr = node.attributes; // 解析屬性 for (var i = 0; i < attr.length; i++) { if (attr[i].nodeName == "v-model") { var name = attr[i].nodeValue; // 獲取v-model綁定的屬性名 node.addEventListener("input", function (e) { // 給相應的data屬性賦值,進而觸發該屬性的set方法 // 觸發set vm[name] vm[name] = e.target.value; }); // node.value = vm[name]; // 將data的值賦給該node new Watcher(vm, node, name, "value"); } }; } //節點類型為text if (node.nodeType === 3) { if (reg.test(node.nodeValue)) { var name = RegExp.$1; // 獲取匹配到的字符串 name = name.trim(); // node.nodeValue = vm[name]; // 將data的值賦給該node new Watcher(vm, node, name, "nodeValue"); } } }, }
哦,原來Compile中是渲染html的啊。其中的Watcher是不是監控節點變化,然后給Dep通知的呢?
function Watcher(vm, node, name, type) { Dep.target = this; this.name = name; //text this.node = node; // 節點 this.vm = vm; // vue實例 this.type = type; //nodeValue 當前節點的值 this.update(); Dep.target = null; } Watcher.prototype = { update: function() { this.get(); var batcher = new Batcher(); batcher.push(this); // this.node[this.type] = this.value; // 訂閱者執行相應操作 }, cb:function(){ this.node[this.type] = this.value; // 訂閱者執行相應操作 }, // 獲取data的屬性值 get: function() { this.value = this.vm[this.name]; //觸發相應屬性的get } }
哎呦,咱們猜對了呢,這樣雙向數據綁定馬上就要完成了,只剩一個Vue.nextTick()的地方了
/** * 批處理構造函數 * @constructor */ function Batcher() { this.reset(); } /** * 批處理重置 */ Batcher.prototype.reset = function () { this.has = {}; this.queue = []; this.waiting = false; }; /** * 將事件添加到隊列中 * @param job {Watcher} watcher事件 */ Batcher.prototype.push = function (job) { if (!this.has[job.name]) { this.queue.push(job); this.has[job.name] = job; if (!this.waiting) { this.waiting = true; setTimeout(() => { this.flush(); }); } } }; /** * 執行并清空事件隊列 */ Batcher.prototype.flush = function () { this.queue.forEach((job) => { job.cb(); }); this.reset(); };
看完后是不是覺得超簡單呢?
vue3版本將做出巨大的變化,把Dep跟Watcher都干掉了,html直接跟數據進行綁定,等vue3出來后,在寫一篇關于vue的文章吧
看完后能幫我點個贊嗎?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/108851.html
摘要:學完的基礎語法之后,練手一下,從最基本的留言板開刀吧。功能不多,主要為了熟悉的基礎語法使用。 學完vue的基礎語法之后,練手一下,從最基本的留言板開刀吧。功能不多,主要為了熟悉vue的基礎語法使用。詳細vue教程請移步vue.js 2.0 技術框架 1.vue.js 2.0 2.bootstrap 語法概述 這里只寫一點此例子用到的一些語法知識,詳細API請移步:vue 2.0 a...
摘要:實現的一套博客系統包括博客前端展示頁和博客后臺管理頁貌似預覽圖加載不出來,直接點看吧項目地址簡要技術棧后臺管理頁的編輯器用的,支持語法解析部分使用了這個庫,語法高亮用博客在線地址僅供臨時預覽博客后臺管理頁在線地址僅供臨時預覽博客后臺管理 vue+node 實現的一套博客系統,包括博客前端展示頁和博客后臺管理頁 segmentfault貌似預覽圖加載不出來,直接點?github看吧 項目...
摘要:由于眾所周知的原因,谷歌字體只能過墻后才能被正常加載,而中的原生使用了谷歌字體,在這個案例中改為使用。代碼存在,國內訪問速度沒那么快,初次加載較慢請耐心等待。如果項目對你有所幫助,不妨一下,你的支持是我前進的最大動力。 效果圖: showImg(https://segmentfault.com/img/remote/1460000008172654?w=303&h=545); show...
閱讀 1118·2021-10-09 09:43
閱讀 18475·2021-09-22 15:52
閱讀 1059·2019-08-30 15:44
閱讀 3050·2019-08-30 15:44
閱讀 3244·2019-08-26 14:07
閱讀 904·2019-08-26 13:55
閱讀 2566·2019-08-26 13:41
閱讀 3087·2019-08-26 13:29