強大的observejs

【當耐特】發表於2015-05-07

寫在前面

各大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.

相關文章