寫在前面
各大MVVM框架的雙向繫結太難以觀察,很難直觀地從業務程式碼裡知道發生了什麼,我不是雙向繫結的反對者,只是認為雙向繫結不應該糅合進底層框架,而應該出現在業務程式碼中,或者是業務和框架之間的程式碼上,由開發者實現,由開發者決定觀察什麼,決定響應什麼。
以及Object.observe的支援度不夠好(http://caniuse.com/#search=observe)
再者Object.observe的功能太弱(如物件內陣列的變化無法監聽)。
所以就有了observejs。
observe.js意義
- 監聽任意物件的任意資料變化
- 作為業務和框架之間的中介軟體存在
- 作為mv*框架中的監聽模組(當然我是相當反對)
3分鐘精通observe.js
物件字面量
var obj = { a: 1 };
//watch obj
observe(obj, function (name, value) {
console.log(name + "__" + value);//a__2
});
obj.a = 2;
陣列
var arr = [1, 2, 3];
//watch obj
observe(arr, function (name, value, old) {
console.log(name + "__" + value+"__"+old);
});
arr.push(4);//array__push
arr[3] = 5;//3__5
複雜物件
var complexObj = { a: 1, b: 2, c: [{ d: [4] }] };
//watch complexObj
observe(complexObj, function (name, value) {
console.log(name + "__" + value); //d__100
});
complexObj.c[0].d = 100;
普通物件
var User = function (name, age) {
this.name = name;
this.age = age;
//watch User's instance
observe(this, function (name, value, oldValue) {
console.log(name + "__" + value + "__" + oldValue);//name__wangwu__lisi
});
}
var user = new User("lisi", 25);
user.name = "wangwu";
原理
監聽物件
利用Object.defineProperty,以及內建 "__屬性名" 來儲存真正的 "屬性名" 的值。
Object.defineProperty(target, prop, {
get: function () {
return this["__" + prop];
},
set: function (value) {
self.onPropertyChanged(prop, value, this["__" + prop]);
this["__" + prop] = value;
}
});
監聽陣列
observe.methods = ["concat", "every", "filter", "forEach", "indexOf", "join", "lastIndexOf", "map", "pop", "push", "reduce", "reduceRight", "reverse", "shift", "slice", "some", "sort", "splice", "unshift", "valueOf"]
observe.triggerStr = ["concat", "pop", "push", "reverse", "shift", "sort", "splice", "unshift"].join(",")
observe.methods.forEach(function (item) {
target[item] = function () {
var result = Array.prototype[item].apply(this, Array.prototype.slice.call(arguments));
for (var cprop in this) {
if (this.hasOwnProperty(cprop) && cprop != "_super" && !observe.isFunction(this[cprop])) {
self.watch(this, cprop);
}
}
if (new RegExp("\\b" + item + "\\b").test(observe.triggerStr)) {
self.onPropertyChanged("array", item, arguments[0]);
}
return result;
};
});
對Array的所有方法進行了mock,上面的target是被監聽的array,其所有方法被重寫,然後內部執行,執行的過程中,如果屬於edit操作,如concat, pop, push等,都會觸發onPropertyChanged。
Github
https://github.com/kmdjs/observejs
現在開始,請愉快地使用吧!
This content is released under the (http://opensource.org/licenses/MIT) MIT License.