3

思路:

  1. 发布订阅模式实现一个观察者;

  2. 将观察者挂在app上;

源码:

console.log('this is vue one.js');

function Observer(data) {
    this.data = data;
    this.walk(data);
    this.eventsBus = new Events();
}
Observer.prototype.walk = function(obj) {
    var val;
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            val = obj[key];

            if (obj[key] instanceof Object) {
                new Observer(obj[key]);
            }

            this.convert(key, val);
        }
    }
}
Observer.prototype.convert = function(key, val) {
    var _this = this;
    Object.defineProperty(this.data, key, {
        enumerable: true,
        configurable: true,
        get: function() {
            console.log('你访问了' + key);
            return val;
        },
        set: function(newVal) {
            console.log('你设置了' + key);
            console.log('新的' + key + '=' + newVal);
            if (val === newVal) {
                return;
            }
            _this.eventsBus.emit(key, newVal, val);
            val = newVal;
        }
    });
}

Observer.prototype.$watch = function (key, callback) {
    this.eventsBus.on(key, callback);
}
//实现事件的发布-订阅
function Events() {
    this.events = {};
}
Events.prototype = {
    constructor: Events,
    on: function(eventType, callback) {
        if (!this.events[eventType]) {
            this.events[eventType] = [];
        }
        this.events[eventType].push(callback);
        return this;
    },
    remove: function(eventType) {
        for (var key in this.events) {
            if (this.events.hasOwnProperty(key) && key === eventType) {
                delete this.events[eventType];
            }
        }
    },
    emit: function(eventType) {
        if (!this.events[eventType]) {
            return this;
        }
        var args = Array.prototype.slice.call(arguments, 1);
        for (var i = 0; i < this.events[eventType].length; i++) {
            this.events[eventType][i].apply(this, args);
        }
        return this;
    }
}

var data = {
    user: {
        name: "luxixi",
        age: "24"
    },
    address: {
        city: "beijing"
    },
    age: 23
};

var app = new Observer(data);
app.$watch('age', function(val, oldVal) {
    console.log('我的新值是:' + val);
    console.log('我的旧值是:' + oldVal);
});
app.data.user = {name: "Alex"};
app.data.age = 24;

知识点:

  1. 发布订阅模式;

  2. apply和call函数的使用;

  3. arguments是一种特殊的数组但不是数组;

参考文献: 发布订阅模式


Alex
58 声望3 粉丝