MVVM(一)資料代理原始碼分析
阿新 • • 發佈:2018-12-17
1:準備工作API瞭解
- 1. [].slice.call(lis): 將偽陣列轉換為真陣列
2. node.nodeType: 得到節點型別
3. Object.defineProperty(obj, propertyName, {}): 給物件新增屬性(指定描述符)
4. Object.keys(obj): 得到物件自身可列舉屬性組成的陣列
5. obj.hasOwnProperty(prop): 判斷prop是否是obj自身的屬性
6. DocumentFragment: 文件碎片(高效批量更新多個節點)
MVVM原始碼分析:
(一)資料代理實現
1.vue資料代理: data物件的所有屬性的操作(讀/寫)由vm物件來代理操作
2. 好處: 通過vm物件就可以方便的操作data中的資料
3. 實現:
1). 通過Object.defineProperty(vm, key, {})給vm新增與data物件的屬性對應的屬性
2). 所有新增的屬性都包含get/set方法
3). 在get/set方法中去操作data中對應的屬性
function MVVM(options) { // 將選項物件儲存到vm this.$options = options; // 將data物件儲存到vm和datq變數中 var data = this._data = this.$options.data; //將vm儲存在me變數中 var me = this; // 遍歷data中所有屬性 Object.keys(data).forEach(function (key) { // 屬性名: name // 對指定屬性實現代理 me._proxy(key); }); } const vm = new MVVM({ el: "#test", data: { name: '張三2' //配置物件的data屬性 } }) console.log(vm.name) // 讀取的是data中的name, vm代理對data的讀操作 vm.name = '李四2' // 資料儲存到data中的name上, vm代理對data的寫操作 // 對指定屬性實現代理 _proxy: function (key) { // 儲存vm var me = this; // 給vm新增指定屬性名的屬性(使用屬性描述) Object.defineProperty(me, key, { configurable: false, // 不能再重新定義 enumerable: true, // 可以列舉 // 當通過vm.name讀取屬性值時自動呼叫 get: function proxyGetter() { // 讀取data中對應屬性值返回(實現代理讀操作) return me._data[key]; }, // 當通過vm.name = 'xxx'時自動呼叫 set: function proxySetter(newVal) { // 將最新的值儲存到data中對應的屬性上(實現代理寫操作) me._data[key] = newVal; } }); } };
實現思路:在建立VM物件的時候,將配置物件的data屬性存放到vm_data裡面,然後data中的屬性通過通過Object.defineProperty(vm, key, {})給vm新增與data物件的屬性對應的屬性,在讀取data屬性的時候呼叫get方法,設定的時候呼叫get方法。
VM物件的$option存放的是配置物件,_data存放的是data的資料,實現讀取data資料都是在_data中讀取。實現關鍵就是Object.defineProperty(vm, key, {});