寫在前面
各大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.