DOM树与控件树
文档对象模型(Document Object Model
,简称DOM
),是W3C
组织推荐的处理可扩展标志语言的标准编程接口,一种独立于平台和语言的方式访问和修改一个文档的内容和结构。换句话说,这是表示和处理一个HTML
或XML
文档的标准接口。简单来说,DOM
就是文档树,与用户界面控件树对应,在前端开发中通常指HTML
对应的渲染树,但广义的DOM
也可以指Android
中的XML
布局文件对应的控件树,而术语DOM
操作就是指直接来操作渲染树(或控件树), 因此,可以看到其实DOM
树和控件树是等价的概念,只不过前者常用于Web
开发中,而后者常用于原生开发中。
响应式编程(Reactive Programming)
React
中提出一个重要思想:状态改变则UI
随之自动改变,而React
框架本身就是响应用户状态改变的事件而执行重新构建用户界面的工作,这就是典型的响应式编程范式,下面我们总结一下React
中响应式原理:
- 开发者只需关注状态转移(数据),当状态发生变化,
React
框架会自动根据新的状态重新构建UI
。 React
框架在接收到用户状态改变通知后,会根据当前渲染树,结合最新的状态改变,通过Diff
算法,计算出树中变化的部分,然后只更新变化的部分(DOM
操作),从而避免整棵树重构,提高性能。
值得注意的是,在第二步中,状态变化后React
框架并不会立即去计算并渲染DOM
树的变化部分,相反,React
会在DOM
的基础上建立一个抽象层,即虚拟DOM
树,对数据和状态所做的任何改动,都会被自动且高效的同步到虚拟DOM
,最后再批量同步到真实DOM
中,而不是每次改变都去操作一下DOM
。为什么不能每次改变都直接去操作DOM
树?这是因为在浏览器中每一次DOM
操作都有可能引起浏览器的重绘或回流:
- 如果
DOM
只是外观风格发生变化,如颜色变化,会导致浏览器重绘(repaint
)界面。 - 如果
DOM
树的结构发生变化,如尺寸、布局、节点隐藏等导致,浏览器就需要回流(reflow
)(及重排-重新排版布局)。
而浏览器的重绘和回流都是比较昂贵的操作,如果每一次改变都直接对DOM
进行操作,这会带来性能问题,而批量操作只会触发一次DOM
更新。
思考题:
Diff
操作和DOM
批量更新难道不应该是浏览器的职责吗?第三方框架中去做合不合适?摘自:https://book.flutterchina.club/chapter1/mobile_development_intro.html
参考阅读文章
- 《浏览器重绘(repaint)和重排(reflow)》-https://www.jianshu.com/p/fe64e387d5bc
- 《前端性能优化:细说浏览器渲染的重排与重绘》-http://www.imooc.com/article/45936
- 《JavaScript——浏览器的重绘与回流》-https://blog.csdn.net/qq_42269433/article/details/81133772
发表回复