React学习20220314 虚拟DOM

React学习20220314 虚拟DOM

虚拟DOM是什么

是JS和DOM之间的一个映射缓存,在形态上表现为一个能够描述DOM结构及其属性信息的JS对象。

在REACT中,表现为

image-20220314142105501

是JS对象,是对真实DOM的描述

如何工作

  • 挂载阶段:结合JSX的描述,构建出虚拟DOM树,然后通过ReactDOM.render实现虚拟DOM到真实DOM的映射
  • 更新阶段,页面的变化在作用于真实DOM之前,先作用于虚拟DOM,虚拟DOM在JS层借助算法先对比出那些真实DOM需要被改变,然后将改变作用于真实DOM

这一段历史讲得好有趣,摘下来

image-20220314142856250

image-20220314145559439

image-20220314145616729

可以看出,模板语法其实就是把 JS 和 HTML 结合在一起的一种规则,而模板引擎做的事情也非常容易理解。

把 staff 这个数据源读进去,塞到预置好的 HTML 模板里,然后把两者融合在一起,吐出一段目标字符串给你。这段字符串的内容,其实就是一份标准的、可用于渲染的 HTML 代码,它将对应一个 DOM 元素。最后,将这个 DOM 元素挂载到页面中去,整个模板的渲染流程也就走完了。

这个过程可以用伪代码来表示,如下所示:

// 数据和模板融合出 HTML 代码
var targetDOM = template({data: students})
// 添加到页面中去
document.body.appendChild(targetDOM)

当然,实际的过程会比我们描述的要复杂一些。这里我补充一下模板引擎的实现思路,供感兴趣的同学参考。模板引擎一般需要做下面几件事情:

  1. 读取 HTML 模板并解析它,分离出其中的 JS 信息;

  2. 将解析出的内容拼接成字符串,动态生成 JS 代码;

  3. 运行动态生成的 JS 代码,吐出“目标 HTML”;

  4. 将“目标 HTML”赋值给 innerHTML,触发渲染流水线,完成真实 DOM 的渲染。

使用模板引擎方案来渲染数据是非常爽的:每次数据发生变化时,我们都不用关心到底是哪里的数据变了,也不用手动去点对点完成 DOM 的修改。只需要关注的仅仅是数据和数据变化本身,DOM 层面的改变模板引擎会帮我们做掉。

如此看来,模板引擎像极了一个只需要接收命令,就能够把活干得漂漂亮亮的“扫地机器人”!可惜的是,模板引擎出现的契机虽然是为了使用户界面与业务数据相分离,但实际的应用场景基本局限在“实现高效的字符串拼接”这一个点上,因此不能指望它去做太复杂的事情。尤其令人无法接受的是,它在性能上的表现并不尽如人意:由于不够“智能”,它更新 DOM 的方式是将已经渲染出 DOM 整体注销后再整体重渲染,并且不存在更新缓冲这一说。在 DOM 操作频繁的场景下,模板引擎可能会直接导致页面卡死。

注:请注意小标题中“早期”这个限定词——本课时所讨论的“模板引擎”概念,指的是虚拟 DOM 思想推而广之以前,相对原始的一类模板引擎,这类模板引擎曾经主导了一个时代。但时下来看,越来越多的模板引擎正在引入虚拟 DOM,模板引擎最终也将走向现代化。

虽然指望模板引擎实现生产力解放有些天方夜谭,但模板引擎在思想上无疑具备高度的先进性:允许程序员只关心数据而不必关心 DOM 细节的这一操作,和 React 的“数据驱动视图”思想如出一辙,实在是高!

那该怎么办呢?

jQuery 救不了加班写 DOM 操作的前端,模板引擎也救不了,那该怎么办呢?

这时候有一批仁人志士,兴许是从模板引擎的设计思想上得到了启发,他们明确了要走“数据驱动视图”这条基本道路,于是便沿着这个思路往下摸索:模板引擎的数据驱动视图方案,核心问题在于对真实 DOM 的修改过于“大刀阔斧”,导致了 DOM 操作的范围过大、频率过高,进而可能会导致糟糕的性能。然后这帮人就想啊:既然操作真实 DOM 对性能损耗这么大,那我操作假的 DOM 不就行了?

沿着这个思路再往下走,就有了我们都爱的虚拟 DOM。

注:出于严谨,还是要解释下。真实历史中的虚拟 DOM 创作过程,到底有没有向模板引擎去学习,这个暂时无从考证。但是按照前端发展的过程来看,模板引擎和虚拟 DOM 确实在思想上存在递进关系,很多场景下,面试官也可能会问及两者的关系。因此在此处,我采取了这样一种表述方式,希望能够帮助你更好地把握住问题的关键所在。

虚拟DOM使得之前的全局刷新,改成了有更新的部分更新,在真实DOM前加了一层

image-20220314151706530

虚拟DOM解决的问题重心不是性能

image-20220314151854443

Reconciliation过程与Diff算法

Diff算法

找两个树结构之间的不同

两个规律

image-20220314152249841

image-20220314153544145

对于Key,下图可以比较好地展示使用了Key后的更新策略

image-20220314153745501

如果不使用key,则仅有AB可保留,其他均被重建

Author

YSH

Posted on

2022-03-16

Updated on

2022-10-12

Licensed under