来源:https://segmentfault.com/a/1190000004384515
(function(){
//Observer
var Observer = cc.Class.extend({
ctor: function(value){
this.value = value;
this.walk(value);
},
walk: function(value){
Object.keys(value).forEach(function(key, ind, arr){
this.convert(key,value[key]);
},this);
},
convert: function(key, val){
defineReactive(this.value, key, val);
}
});
var defineReactive = function(obj, key, val){
var dep = new Dep();
var childOb = observer(val);
Object.defineProperty(obj, key, {
enumberable: true,
configurable: true,
get: function(){
console.log("get");
if(Dep.target){
dep.addSub(Dep.target);
}
return val;
},
set: function(newValue){
console.log("set",newValue);
var value = val;
if(newValue === value){
return;
}
childOb = observer(newValue);
dep.notify();
}
})
};
var observer = function(value, vm){
if (!value || typeof value !== 'object') {
return;
}
return new Observer(value);
};
//订阅器
var Dep = cc.Class.extend({
ctor: function(){
this.subs = [];
},
addSub:function(sub){
this.subs.push(sub);
},
notify:function(){
this.subs.forEach(function(sub, ind, arr){
sub.update();
})
},
});
Dep.target = null
//watcher
var Watcher = cc.Class.extend({
ctor: function(vm, expOrFn, cb){
this.cb = cb;
this.vm = vm;
//暂时只考虑expression的情况
this.expOrFn = expOrFn;
this.value = this.get();
},
update: function(){
this.run();
},
run: function(){
var value = this.get();
if(value !== this.value){
this.value = value ;
this.cb.call(this.vm);
}
},
get: function(){
Dep.target = this;
//暂时只考虑expression的情况
var value = this.vm._data[this.expOrFn];
Dep.target = null;
return value;
}
});
//Vue
var vue = cc.Class.extend({
ctor: function(options){
this.$options = options || {};
var data = this._data = this.$options.data;
Object.keys(data).forEach(function(key, ind, arr){
this._proxy(key);
},this);
observer(data, this);
},
$watcher: function(expOrFn, cb, options){
new Watcher(this, expOrFn, cb);
},
_proxy: function(key){
var self = this;
Object.defineProperty(self, key, {
configurable: true,
enumberalbe: true,
get:function proxyGetter(){
return self._data[key];
},
set: function proxySetter(val){
self._data[key] = val;
}
});
}
});
mj.vue = vue;
})();