响应式对象原理
这节我们知道对象响应式原理的实现,在此基础上分析vue的响应式
image.png
一、初始化实例_init函数
Vue.prototype._init = function (options) {
......
initInjections(vm); // resolve injections before data/props
......
};
二、查看initInjections函数
function initInjections (vm) {
var result = resolveInject(vm.$options.inject, vm);
if (result) {
......
Object.keys(result).forEach(function (key) {
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
defineReactive$$1(vm, key, result[key], function () {
......
} else {
......
}
});
......
}
}
三、接着查看defineReactive$$1函数
function defineReactive$$1 (
obj,
key,
val,
customSetter,
shallow
) {
var dep = new Dep();
......
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
......
if (Dep.target) {
dep.depend();
......
}
return value
},
set: function reactiveSetter (newVal) {
......
if (setter) {
setter.call(obj, newVal);
} else {
val = newVal;
}
......
dep.notify();
}
});
}
实现的原理实际上也就是把要响应数据用Object.defineProperty改成getter/setter存储器属性:
1.get()函数中调用 dep.depend(),实现this.subs.push(target)
2.set()函数中调用dep.notify();运行this.subs数据中的所有函数,实现存储最新数据的操作
更详细的可以查看 class Dep相关定义
var Dep = function Dep () {
this.id = uid++;
this.subs = [];
};
Dep.prototype.depend = function depend () {
if (Dep.target) {
Dep.target.addDep(this);
}
};
Dep.prototype.notify = function notify () {
// stabilize the subscriber list first
var subs = this.subs.slice();
if (process.env.NODE_ENV !== 'production' && !config.async) {
// subs aren't sorted in scheduler if not running async
// we need to sort them now to make sure they fire in correct
// order
subs.sort(function (a, b) { return a.id - b.id; });
}
for (var i = 0, l = subs.length; i < l; i++) {
subs[i].update();
}
};
注意:Dep.target就是watcher实例,即是一个对象
?同一时间只有一个watcher可以被push进targetStack
Dep.target = null;
var targetStack = [];
function pushTarget (target) {
targetStack.push(target);
Dep.target = target;
}
function popTarget () {
targetStack.pop();
Dep.target = targetStack[targetStack.length - 1];
}