ES6 Proxy实现Vue的变化检测问题

2020-06-13 10:39:07易采站长站整理

return;
}
if (Array.isArray(target)) {
if (key === 'length' && target.__parent__) {
target.__parent__.__dep__.notify(keyBefore);
}
} else {
dep.notify(key);
}
}
obeserve(target) {
// 只处理对象类型,包括数组、对象
if (!isObject(target)) return;
for (let key in target) {
if (isObject(target[key]) && target[key] !== null) {
this.obeserve(target[key]);
target[key] = this.proxyTarget(target[key], key);
// 设置__parent__,方便子元素调用
target[key].__parent__ = target;
}
}
}
}

在Observer中,针对对象,只需要执行

 dep.depend(key)
 dep.notify(key)
即可。添加 key 是为了能正确的触发收集,不知道怎么说明白为什么要这样做,只能一切尽在不言中了。

Array, 如何实现依赖的收集和触发那。依赖收集与Object类似, 

dep.depend(key)
完成数组的收集。关于触发,可以分为两个方面,一是改变数组长度、二未改变数组长度的。改变数组长度的,在set里,通过长度属性的设置触发父级元素的notify。为什么要使用父级元素的notify那?我们可以分析以下,在你设置数组的长度时,这时候的targetkeyvalue分别是[]length*, 这个时候,数组的依赖收集是没有的,你watcher的是数组,并不是数组本身。这个时候只能通过 
target.__parent__.__dep__.notify(keyBefore) 
触发父级的收集,完成数据变化的检测。二对于未改变数组长度的,这里的做法,虽然是直接 target.__parent__.__dep__.notify(keyBefore) 触发依赖,但是有个严重的问题,实际上更新的数据不是最新的,这个地方暂时还没想到比较好的方法,欢迎大家讨论。

Dep

Dep.js


let uid = 0;
export default class Dep {
constructor () {
this.subs = {};
this.id = uid++;
}
addSub(prop, sub) {
this.subs[prop] = this.subs[prop] || [];
this.subs[prop].push(sub);
}
removeSub(prop, sub) {
this.remove(this.subs[prop] || [], sub);
}
depend(prop) {
if (Dep.target) {
// 传入的是当前依赖
Dep.target.addDep(prop, this)
}
}
notify(prop) {
const subs = (this.subs[prop] || []).slice();
for (let i = 0, l = subs.length; i < l; i++) {
subs[i].update();
}
}
remove(arr, item) {
if (arr.length) {
const index = arr.indexOf(item);
if (index > -1) {
return arr.splice(index, 1);