1. 数据初始化: 在创建 Vue 实例时,Vue 会遍历 data 选项的所有属性,并使用 Object.defineProperty 将其转换为 getter 和 setter。这样一来,当访问或修改这些属性时,就会触发相应的 getter 和 setter 方法。
var vm = new Vue({
data: {
message: 'Hello, Vue!'
}
});
2. Getter: 当访问属性时,会触发 getter 方法,Vue 在这里会进行依赖收集。每个属性都有一个对应的依赖集合,用来存储当前属性的所有依赖项(观察者)。
3. Watcher: 在模板中使用了数据绑定,Vue 会创建一个 Watcher 实例。Watcher 负责将视图与依赖的属性关联起来。当依赖的属性发生变化时,Watcher 就会通知视图进行更新。
4. Setter: 当修改属性时,会触发 setter 方法。setter 方法会通知之前收集的依赖项(Watcher)进行更新,保证视图与数据的同步。
下面是一个简单的例子,演示了 Vue.js 2.0 的响应式原理:
function defineReactive(obj, key, val) {
var dep = new Dep();
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function () {
if (Dep.target) {
// 添加依赖
dep.addDep(Dep.target);
}
return val;
},
set: function (newVal) {
if (newVal === val) {
return;
}
val = newVal;
// 通知所有依赖进行更新
dep.notify();
}
});
}
// 依赖收集
function observe(obj) {
if (!obj || typeof obj !== 'object') {
return;
}
Object.keys(obj).forEach(function (key) {
defineReactive(obj, key, obj[key]);
});
}
// Watcher
function Watcher(vm, expOrFn, cb) {
this.vm = vm;
this.expOrFn = expOrFn;
this.cb = cb;
this.value = this.get();
}
Watcher.prototype = {
get: function () {
// 设置当前 Watcher 实例
Dep.target = this;
var value = this.vm[this.expOrFn];
// 重置
Dep.target = null;
return value;
},
update: function () {
var value = this.get();
if (value !== this.value) {
this.value = value;
this.cb.call(this.vm);
}
}
};
// 依赖管理
function Dep() {
this.subs = [];
}
Dep.prototype = {
addDep: function (sub) {
this.subs.push(sub);
},
notify: function () {
this.subs.forEach(function (sub) {
sub.update();
});
}
};
// 示例
var data = {
message: 'Hello, Vue!'
};
observe(data);
new Watcher(data, 'message', function () {
console.log('数据更新了:' + this.message);
});
data.message = 'Vue.js 2.0 深入响应式原理';
这是一个简化的例子,实际上,Vue.js 还涉及到数组的响应式处理、异步更新队列等更复杂的情况。
转载请注明出处:http://www.zyzy.cn/article/detail/4806/Vue