-
Notifications
You must be signed in to change notification settings - Fork 383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
vue早期源码学习系列之五:批处理更新DOM #88
Labels
Comments
this.has = {}; |
Batcher.prototype.push = function (job) {
if (!this.has[job.id]) {
this.queue.push(job);
this.has[job.id] = job;
if (!this.waiting) {
this.waiting = true;
setTimeout(() => {
this.flush();
});
}
}
}; @youngwind 大佬,问一下,这样写的话,app.test中第二次更新的user.name如何覆盖前面的更新。 |
@LiuMengzhou 我的理解是,在例子中,第一第二次的name更新,都指向同一个job对象。第一次把job加入到queue中以后,第二次更新时,是把第一次的job.cb或者job.ctx给覆盖了。 |
@LiuMengzhou 最后更新的name是最终的name |
个人觉得这技巧也是绝了, js对象的无重复key使用, setTimeout事件队列 |
mark |
看Vue的源码一直不明白这个 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
前言
在上一篇 #87 中,我们最后谈到,有一个问题还没有解决,我们来看看是什么问题。如下图所示。
我们可以看到,在函数test中,前后两次更改了user.name的值,对应的DOM元素的更新也执行了两次。(注意,这里的DOM元素更新指的是内存中DOM元素的更新,而非浏览器渲染的更新。因为你从视觉上应该也看得出来,虽然DOM元素更新了两次,但是网页上展示的效果却是只修改了一次。此处更多的资料可以参考这里。)
《高性能js》教导我们:“频繁操作DOM是低效率的”,所以,我们是否能做到说,不管user.name变化了多少次,对DOM的更新只进行一次呢?
答案是可以的,方法是批处理。
批处理这个词我最早接触它是在大学计算机组成原理的课程上,当时觉得这个东西好晦涩难懂,跟自己没啥关系,所以就不管它。经过这次深入的学习,我发现批处理的应用是非常的广泛的,它代表的是对某一类问题的处理模式,不仅仅存在于计算机组成原理中。
我们来看看vue官方文档怎么描述它如何应用批处理:
出处:https://vuejs.org.cn/guide/reactivity.html#异步更新队列
批处理原理
在我眼中的批处理是这样的:将一些事件放到一个任务队列中,等到合适的时机再全部拿出来执行。
js这门语言实现批处理的底层原理是“事件循环”,也就是所谓的"Event Loop"。
如果不清楚js事件循环,请务必搞明白这个概念再往下看。可以参考阮一峰的这篇文章
Batcher
好了,接下来我们正式来看看如何实现批处理更新DOM。
我们需要构造这样一个批处理“类”:Batcher
下面我来说明一下几个关键点:
最后一步,是修改原先watcher的update函数
实现效果如下图所示:
完整的源码请参考这个版本。
React中的批处理
我们在开头提到,批处理是一个广泛应用的思想,在研究vue的批处理的时候,我忽然想起了以前在用react的时候碰到的一个问题, #66 ,里面提到的this.setState是异步的,当时不理解。现在仔细想想,背后的本质也应该是批处理。也就是说,我们在调用setState的时候,并非同步修改了this.state,而是攒到一块再修改this.state。跟我们刚刚把对DOM的修改攒到一块,其实是异曲同工的。
参考资料
后话
随着对vue早期源码的不断学习,我更加坚信从早期源码开始学习是一条走得通的道路。目前虽然已经初步具备动态数据绑定的能力,但是很多细节还有待打磨和推敲。比如对template的编译,比如构建缓存系统提升性能,我得好好想想接下来该往哪个方向走。
The text was updated successfully, but these errors were encountered: