Vue2剥丝抽茧-响应式系统完善
这篇文章主要修之前代码存在的一个问题,废话不多说,上代码!
场景
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 之前把列表另存起来,防止遍历过程中被修改。
相关文章
- Jgit的使用笔记
- 利用Github Action实现Tornadofx/JavaFx打包
- 叹息!GitHub Trending 即将成为历史!
- 微软软了?开源社区讨论炸锅,GitHub CEO 亲自来答
- GitHub Trending 列表频现重复项,前后端都没去重?
- Photoshop Elements 2021版本软件安装教程(mac+windows全版本都有)
- (ps全版本)Photoshop 2020的安装与破解教程(mac+windows全版本都有)
- (ps全版本)Photoshop cc2018的安装与破解教程(mac+windows全版本,包括2023
- 环境搭建:Oracle GoldenGate 大数据迁移到 Redshift/Flat file/Flume/Kafka测试流程
- 每个开发人员都要掌握的:最小 Linux 基础课
- 来撸羊毛了!Windows 环境下 Hexo 博客搭建,并部署到 GitHub Pages
- 超实用!手把手入门 MongoDB:这些坑点请一定远离
- 【GitHub日报】22-10-09 zustand、neovim、webtorrent、express 等4款App今日上新
- 【GitHub日报】22-10-10 brew、minio、vite、seaweedfs、dbeaver 等8款App今日上新
- 【GitHub日报】22-10-11 cobra、grafana、vue、ToolJet、redwood 等13款App今日上新
- Photoshop 2018 下载及安装教程(mac+windows全版本都有,包括最新的2023)
- Photoshop 2017 下载及安装教程(mac+windows全版本都有,包括最新的2023)
- Photoshop 2020 下载及安装教程(mac+windows全版本都有,包括最新的2023)
- Photoshop 2023 资源免费下载(mac+windows全版本都有,包括最新的2023)
- 最新版本Photoshop CC2018软件安装教程(mac+windows全版本都有,包括2023