作者:心葉
時間:2019-07-18 10:34
本文章構思的實現方法在github上有對應的項目已經實現,項目依舊在不斷改進中:abandon.js
核心方法說明
Object.defineProperty(obj,key,{
get(){
// todo1
},
set(newValue){
// todo2
}
});
比如obj是一個json,其有一個值key,也就是obj.key。我們可以通過上面的方法對設置和獲取obj.key的時候進行攔截處理,而這就是js部分雙向綁定的核心。
設計思路
頁面 → JS
監聽輸入框的輸入時間,如果有輸入,就主動改變js中的值,這樣,頁面到js這一條路就通了。
JS → 頁面
js部分通過前面說的Object.defineProperty方法,對需要雙向綁定的數據進行攔截,發現數據改變的時候,就主動去修改頁面顯示,這樣,js到頁面這一條路就通了。
難點
上面的說明看起來很簡單,然而,事實並非如此,主要有下面幾個問題(其實主要是設計的問題):
- js數據改變了,你怎麼知道應該修改頁面中哪些地方?
- 頁面的表達式可能很複雜,如何解析
- 數組或對象如何監聽
實現
主體對象
控制整個流程,餘下的都是由這裏協調資源。
let Abandon = function (options) {
// 管理的數據(雙向綁定)
this._data = options.data || {};
// 對維護的數據進行監聽
this.__observe();
// 獲取掛載點
this.$el = $$(options.el)[0];
// 編譯結點
this.__compile();
}
數據攔截者observe.js
對象options的data中定義的key的編輯會在這裏攔截,通知專門處理變化情況的(同步視圖和數據)。
export default function(){
for (let key in this._data) {
// 定義攔截鉤子
Object.defineProperty(this._data, key, {
get() {
// todo
},
set(newValue) {
// todo
}
});
};
編譯程序compile.js
簡單點說,就是分析結點中的內容,有沒有定義的指令等,根據結點內容追加需要管理的東西。
export default function(){
let nodes = this.$el.childNodes;
for (let i = 0; i < nodes.length; i++) {
// 如果不是文本結點,繼續編譯
if (node.nodeType !== 3) {
// todo
}
// 開始正式解析一個結點(分爲文本結點和非文本結點)
// 解析的意思就是標記需要管理的屬性,文本等
if (node.nodeType === 3) {
// 如果是文本
} else {
// 如果不是文本
}
}
};
後記
上面力求簡單,具體的代碼沒有顯示出來,如果需要看具體代碼,請去github/abandon.js上查看。