- DOM的缺陷
- JS操作DOM时会影响到整个渲染流水线的。
- DOM提供了一组JS接口用来遍历或者修改节点,这会引发重排或者重绘。
- 强制同步布局和布局抖动问题也大大降低渲染效率。
- 复杂的页面,DOM结构也就复杂,没触发一次重排或者重绘都是非常耗时的。
- 什么是虚拟DOM
- 将页面改变的内容应用到虚拟DOM上,而不是直接应用到DOM上。
- 变化被应用到虚拟DOM上时,虚拟DOM不是去渲染页面,而是调整虚拟DOM的内部状态,这样操作虚拟DOM的代价就变得很轻。
- 在虚拟DOM收集到足够的改变时,再把这些变化一次性应用到真实的DOM上。
- 虚拟DOM运行原理
- 创建阶段:首先根据JSX和急促和数据创建虚拟DOM,它反映了真实的DOM树的结构,然后由虚拟DOM树创建出真实DOM树,真实的DOM树生成完后,再触发渲染流水线往屏幕输出页面。
- 更新阶段:如果数据发生改变,那么就需要根据新的数据创建一个新的虚拟DOM树;然后比较新旧虚拟DOM树,找出变化的地方,并把变化的地方一次性更新到真实的DOM树上;最后渲染引擎更新渲染流水线,并生成新的页面。
- 新旧2个虚拟DOM比较的过程时再一个递归函数里执行,其核心算法时reconciliation。但是当虚拟DOM复杂的是会,该递归函数执行占据主线程比较久的时间,这就会导致其他任务等待造成页面卡顿,为解决该问题,React团队重写了reconciliation算法,新的算法称为Fiber reconciler,之前的老算法称为 Stack reconciler。Fiber是协程的另一个称呼,Fiber reconciler就是再算法执行过程中让出主线程,这样就解决了Stack reconciler函数占用时间过久问题。
- 什么是双缓存
- 使用双缓存,可以让计算的中间结果存放再另一个缓冲区中,等全部的计算结束该缓冲区已经存储了完整的图形,再将该缓冲区的图形数据一次性复制到显示缓冲区,这样就使得整个图像的输出非常稳定。
- 虚拟DOM可以看成是DOM的一个buffer(缓冲器),套用双缓存的概念,就达到了稳定输出DOM的效果。
- 本质上:虚拟DOM是一种类似双缓存的实现。
- MVC模式
- MVC:它能将数据和视图进行分离,再涉及到一些复杂的项目时,能大大减轻项目的耦合度,使得程序易于维护。
- 它由模型(Model)、视图(View)和控制器(controller)组成,其核心思想就是将数据和视图分离。也就是视图和模型之间是不允许直接通信的,它们之间的通信都是通过控制器来完成的。
- 可以将React的虚拟DOM部分看成是MVC中的视图部分,其控制器和模型都是由redux提供的。
- 控制器用来监控DOM变化, 一旦DOM发生变化,控制器就通知模型让其跟新数据。
- 模型数据更新好之后,控制器会通知视图告诉它模型的数据发生了变化。
- 视图接收到更新消息之后,会更具模型所提供的数据来生成新的虚拟DOM。
- 新的虚拟DOM生成好之后,就需要与之前的虚拟DOM进行比较,找茬变化的节点。
- 比较出变化的节点之后,React将变化的虚拟节点应用到DOM上,这样就会触发DOM节点的更新。
- DOM 节点的变化又会触发后续一系列渲染流水线的变化,从而实现页面的更新。