function Dep() {
this.subs = [];
}
Dep.prototype.addSub = function(sub) {
this.subs.push(sub);
};
Dep.prototype.notify = function() {
var subs = this.subs.slice();
for(var i = 0; i < subs.length; i++) {
subs[i].update();
}
}
利用 Dep 将上面的代码改写下就好了(当然,此处的 Dep 代码也不完全,只是一个大概的意思罢了)。
Vue 实例代理 data 对象
官方文档中有这么一句话:
每个 Vue 实例都会代理其 data 对象里所有的属性。
var data = { a: 1 };
var vm = new Vue({data: data});vm.a === data.a // -> true
// 设置属性也会影响到原始数据
vm.a = 2
data.a // -> 2
// ... 反之亦然
data.a = 3
vm.a // -> 3
这种代理看起来很麻烦,其实也是可以通过 Object.defineProperty 来实现的:
function Vue(options) {
var data = this.data = options.data; var keys = Object.keys(data);
var i = keys.length;
while(i--) {
proxy(this, keys[i];
}
}
function proxy(vm, key) {
Object.defineProperty(vm, key, {
configurable: true,
enumerable: true,
// 直接获取 vm.data[key] 的值
get: function() {
return vm.data[key];
},
// 设置值的时候直接设置 vm.data[key] 的值
set: function(val) {
vm.data[key] = val;
}
};
}
捏出一个 Vue,实现最初目标
var Vue = (function() {
var Watcher = function Watcher(vm, exp, cb) {
this.vm = vm;
this.exp = exp;
this.cb = cb;
this.value = this.get();
};
Watcher.prototype.get = function get() {
Dep.target = this;
var value = this.vm._data[this.exp];
Dep.target = null;
return value;
};
Watcher.prototype.addDep = function addDep(dep) {
dep.addSub(this);
};
Watcher.prototype.update = function update() {
this.run();
};
Watcher.prototype.run = function run() {
this.cb.call(this.vm);
} var Dep = function Dep() {
this.subs = [];
};
Dep.prototype.addSub = function addSub(sub) {
this.subs.push(sub);
};
Dep.prototype.depend = function depend() {
if(Dep.target) {
Dep.target.addDep(this);
}
};
Dep.prototype.notify = function notify() {
var subs = this.subs.slice();
for(var i = 0; i < subs.length; i++) {
subs[i].update();
}
};
Dep.target = null;
var Observer = function Observer(value) {
this.value = value;
this.dep = new Dep();
this.walk(value);
};
Observer.prototype.walk = function walk(obj) {
var keys = Object.keys(obj);










