思路:
发布订阅模式实现一个观察者;
将观察者挂在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;
知识点:
发布订阅模式;
apply和call函数的使用;
arguments是一种特殊的数组但不是数组;
参考文献: 发布订阅模式