您现在的位置是:亿华云 > 数据库

Vue2剥丝抽茧-响应式系统完善

亿华云2025-10-03 18:24:24【数据库】6人已围观

简介这篇文章主要修之前代码存在的一个问题,废话不多说,上代码!场景import { observe } from "./reactive";import Watcher from "./watcher";

这篇文章主要修之前代码存在的丝抽一个问题,废话不多说,茧响上代码!

场景import { observe } from "./reactive";

import Watcher from "./watcher";

const data = {

text: "hello,应式 world",

};

observe(data);

let show = true;

const updateComponent = () => {

if (show) {

console.log(data.text);

show = false;

}

};

new Watcher(updateComponent);

new Watcher(() => console.log("依赖", data.text));

data.text = "123";

先可以 1 分钟思考一下会输出什么。

new Watcher(updateParentComponent);

执行 updateParentComponent 函数,系统输出 hello,完善 world,并且 text 的丝抽 Dep 收集该 Watcher 。

new Watcher(() => console.log("依赖",茧响 data.text));

执行匿名函数,输出 依赖 hello,应式 world ,并且 text 的系统 Dep 收集该 Watcher 。

data.text = "123"; 。完善

触发 text 的丝抽 set,依次执行 Dep 中的茧响 Watcher 。

先执行 updateParentComponent 。应式

const updateComponent = () => {

if (show) {

console.log(data.text);

show = false;

}

};

由于之前已经执行过一次了,系统此时 show 就是完善 false 了,什么都不会输出。网站模板

再执行 () => console.log("依赖", data.text) ,输出 依赖 hello, world。

是的,上边是我们所期望的样子,但事实上输出结果如下:

出错代码 dep.js:37:26 如下:

调用 update 的时候是,遍历过程中 subs[i] 变成了 undefined ,导致了报错。

需要回忆下 Vue2剥丝抽茧-响应式系统之分支切换 这篇文章里我们做了什么。

如果 Watcher 中的函数不再依赖当前属性,我们就把当前 Watcher 从该属性的 Dep 中移除。

而移除其实就是调用了数组的 splice 方法,云服务器直接将 Dep 中的 subs 数组元素进行删除。

removeSub(sub) {

remove(this.subs, sub);

}

export function remove(arr, item) {

if (arr.length) {

const index = arr.indexOf(item);

if (index > -1) {

return arr.splice(index, 1);

}

}

}

而此时我们正在遍历 subs 数组:

notify() {

for (let i = 0, l = this.subs.length; i < l; i++) {

this.subs[i].update();

}

}

对应上边的例子,原本 subs 数组两个 Watcher,第一个 Watcher 执行的时候没有访问 data.text 属性,就要把这一个 Watcher 删除了,第二个就移动到第一个的位置了,此时 for 循环中访问第二个位置的 Watcher 因为被移到前边自然就报错了。

修改起来也很容易,我们只需要在循环前,将原有的 subs 数组保存给一个新的数组即可。

notify() {

// stabilize the subscriber list first

const subs = this.subs.slice();

for (let i = 0, l = subs.length; i < l; i++) {

subs[i].update();

}

}总结

这篇文章比较简单,主要就是循环通知 Watcher 之前把列表另存起来,防止遍历过程中被修改。源码下载

很赞哦!(9432)