摘要:是一個輕巧的框架它實現(xiàn)了數(shù)據(jù)的雙向綁定并提供一些基本的指令幫助你提升效率,比如,,,,是的,如你所見,以開頭的指令是它的獨特標識行左右的代碼量,讓應用的開發(fā)和加載的一瞬完成倉庫訂閱清單前文說到提供了一個強大的接口我們就用它來劫持數(shù)據(jù)不過在此
BiuJS
BiuJS是一個輕巧的mvvm框架訂閱清單
它實現(xiàn)了數(shù)據(jù)的雙向綁定
并提供一些基本的指令幫助你提升效率,比如$for,$model,$if,$click,$style
是的,如你所見,以$開頭的指令是它的獨特標識
1000行左右的代碼量,讓應用的開發(fā)和加載biu的一瞬完成
BiuJS倉庫: https://github.com/veedrin/biu
前文說到JavaScript提供了一個強大的接口Object.defineProperty
我們就用它來劫持數(shù)據(jù)
不過在此之前,我們還有一點準備工作要做
還記得前文提過的數(shù)組(訂閱清單)嗎?我們要造一個數(shù)組來裝東西
其實很簡單
function Dep() { this.subs = []; } Dep.prototype.addSub = function(sub) { this.subs.push(sub); }; Dep.prototype.notify = function(newValue) { for (let i = 0; i < this.subs.length; i++) { this.subs[i].update(newValue); } };
真的就是造個數(shù)組這么簡單
再來一個添加數(shù)組成員的方法,一個遍歷數(shù)組的方法
因為Dep.prototype.notify觸發(fā)的開關在setter那里,也就是說前者依賴后者。Dep取其依賴之意
為了方便,我們還有一個取巧的地方,把訂閱者掛到Dep名下,作為Dep的靜態(tài)屬性緩存起來
function Dep() { this.subs = []; } Dep.target = null; Dep.prototype.addSub = function(sub) { this.subs.push(sub); }; Dep.prototype.notify = function(newValue) { for (let i = 0; i < this.subs.length; i++) { this.subs[i].update(newValue); } };劫持對象屬性
然后再回過頭來說劫持的事
BiuJS主方法傳進來的data是一個對象,我們把它轉成數(shù)組再遍歷
Object.keys(data).forEach((key) => { let value = data[key]; let dep = new Dep; Object.defineProperty(data, key, { enumerable: true, configurable: true, get: function() { Dep.target && dep.addSub(Dep.target); return value; }, set: function(newValue) { if (value === newValue) { return; } value = newValue; dep.notify(newValue); } }); });
每個屬性都會得到一個訂閱清單的實例,用來放它的訂閱者
getter負責把訂閱者添加進來,setter負責通知訂閱者更新
訂閱者是什么時候掛到Dep.target上的?這個我們暫且不表
有一個問題,data可能是嵌套的對象,而且可能嵌套的很深,所以我們要用遞歸深度劫持
Observer.prototype.observe = function(data) { if (!data || typeof data !== "object") { return; } let self = this; Object.keys(data).forEach((key) => { let value = data[key]; // do something self.observe(value); }); };
遞歸停止的條件就是(嵌套)data為空,或者(嵌套)data不是對象
劫持數(shù)組方法問題又來了,假如(嵌套)data的值是數(shù)組呢?
我們來看一個例子
let data = { key: [1, 2] }; let value = data.key; Object.defineProperty(data, "key", { enumerable: true, configurable: true, get: function() { return value; }, set: function(newValue) { value = newValue; console.log("captured"); } }); data.key = [1, 2, 3]; // 控制臺打印"captured" data.key.push(3); // 控制臺沒有打印
數(shù)組本身變化是可以被捕捉到的,用方法操作數(shù)組,setter也很絕望啊
不要悲傷,不要絕望,數(shù)組開外掛,我們就查外掛
Object.defineProperty是對象的方法呀,難道要讓數(shù)組變性嗎?
是的
let arrayObject = Object.create(Array.prototype); console.log(arrayObject); // Array{}
有了它,我們就可以查外掛了
let arrayProto = Array.prototype; let arrayObject = Object.create(arrayProto); let methods = ["push", "pop", "unshift", "shift", "slice", "splice", "concat"]; methods.forEach((method) => { let origin = arrayProto[method]; Object.defineProperty(arrayObject, method, { enumerable: true, writable: true, configurable: true, value: function() { let args = Array.from(arguments); let result = origin.apply(this, args); dep.notify(Array.from(this)); return result; } }); });
上面的意思就是來一個偷天換日,把數(shù)組的方法名的value換成我們自己定義的函數(shù)
因為是數(shù)組的方法,這里的this指向的就是被操作的數(shù)組本身
在內部還是用apply調用原方法,獲得返回值返回給我們自己定義的函數(shù)
在外面看起來是一樣的,只不過加了一條:悄悄的通知訂閱者更新
這回我們不需要勞煩setter了,數(shù)組的方法不是繞過了setter么,我們只要拿到操作完后的新數(shù)組,遞給訂閱者就好了
簡直就是碟中諜有沒有!
當然,要達到效果,還需要最后一招:移花接木
methods.forEach((method) => { let origin = arrayProto[method]; Object.defineProperty(arrayObject, method, { // do something }); }); arr.__proto__ = arrayObject;
把我們自己定義的方法嫁接到被監(jiān)測數(shù)組的原型上
一招偷天換日,一招碟中諜,一招移花接木
殊不知,我們已經在數(shù)組的方法身上植入了芯片,外掛game over
最后,遞歸的時候,我們要判斷一下,對象和數(shù)組走的是不同的路
if (!Array.isArray(value)) { this.observe(value); } else { this.observeArray(value, dep); }寫在后面
以上就是BiuJS劫持數(shù)據(jù)以及添加到訂閱清單里的過程
歡迎到BiuJS倉庫: https://github.com/veedrin/biu了解詳情
更歡迎Star和Fork
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/92278.html
摘要:是一個輕巧的框架它實現(xiàn)了數(shù)據(jù)的雙向綁定并提供一些基本的指令幫助你提升效率,比如,,,,是的,如你所見,以開頭的指令是它的獨特標識行左右的代碼量,讓應用的開發(fā)和加載的一瞬完成倉庫啟動首先我們來看一下是如何啟動的是的掛載點,它決定在多大范圍的樹 showImg(https://segmentfault.com/img/remote/1460000012478667?w=1920&h=926...
摘要:是一個輕巧的框架它實現(xiàn)了數(shù)據(jù)的雙向綁定并提供一些基本的指令幫助你提升效率,比如,,,,是的,如你所見,以開頭的指令是它的獨特標識行左右的代碼量,讓應用的開發(fā)和加載的一瞬完成倉庫指令往下看之前,請大家沐浴更衣,因為我要講的指令了中的已經被占用 showImg(https://segmentfault.com/img/remote/1460000012478667?w=1920&h=926...
摘要:如此循環(huán),直到結束如果循環(huán)結束之后,比字符串的長度要小,那說明后面還有文本匹配失敗了。 showImg(https://segmentfault.com/img/remote/1460000012478667?w=1920&h=926); BiuJS BiuJS是一個輕巧的mvvm框架它實現(xiàn)了數(shù)據(jù)的雙向綁定并提供一些基本的指令幫助你提升效率,比如$for,$model,$if,$cli...
摘要:一背景團隊最近頻繁遭受網絡攻擊,引起了技術負責人的重視,筆者在團隊中相對來說更懂安全,因此花了點時間編輯了一份安全開發(fā)自檢清單,覺得應該也有不少讀者有需要,所以將其分享出來。 一、背景 團隊最近頻繁遭受網絡攻擊,引起了技術負責人的重視,筆者在團隊中相對來說更懂安全,因此花了點時間編輯了一份安全開發(fā)自檢清單,覺得應該也有不少讀者有需要,所以將其分享出來。 二、編碼安全 2.1 輸入驗證 ...
摘要:一背景團隊最近頻繁遭受網絡攻擊,引起了技術負責人的重視,筆者在團隊中相對來說更懂安全,因此花了點時間編輯了一份安全開發(fā)自檢清單,覺得應該也有不少讀者有需要,所以將其分享出來。 一、背景 團隊最近頻繁遭受網絡攻擊,引起了技術負責人的重視,筆者在團隊中相對來說更懂安全,因此花了點時間編輯了一份安全開發(fā)自檢清單,覺得應該也有不少讀者有需要,所以將其分享出來。 二、編碼安全 2.1 輸入驗證 ...
閱讀 1376·2021-11-15 18:11
閱讀 2508·2021-08-19 10:56
閱讀 669·2021-08-09 13:42
閱讀 785·2019-08-30 15:53
閱讀 2078·2019-08-30 10:55
閱讀 3137·2019-08-29 17:18
閱讀 1427·2019-08-29 13:45
閱讀 537·2019-08-29 13:15