虚拟DOM
是什么:
一个能代表DOM树的对象,含有标签名、标签上属性、事件监听和子元素等等。
优点:
-
减少DOM操作
- 虚拟DOM可以将多次操作合并
- 借助DOM diff,可以省去多余操作,比如添加10个节点,如果借助对比,就可以只操作这10次添加
-
跨平台
虚拟DOM本质是JS对象,可以应用到其他平台。
虚拟DOM的样子:
小缺点:
创建虚拟DOM:
使用React.createElement(),就是使用了额外的创建函数。
但是可以使用JSX简化创建虚拟DOM。
简化后,随之而来也带来额外的工作:因为js需要依赖打包工具来认识JSX
与操作节点的规模有关:
当数据规模不是特别大的时候,虚拟DOM是快的;当规模太大的时候,虚拟DOM的一些操作反而会花更多时间。
DOM diff
每次都比较根节点,然后递归地比较子节点。
-
仅修改了标签上的属性
仅更新对应的DOM属性即可。
-
删除了左子树
DOM diff长什么样:
本质是一个函数,参数是两个虚拟DOM,输出参数是一个补丁,补丁队列是对真实DOM的增量。
patches = ppatch(oldVNode, newVNode)
补丁队列:
patches:
[
{type:'INSERT', vNode:...}
{type:'TEXT', vNode:...}
{type:'PROPS', propsPatch:[]}
]
diff核心逻辑:
Tree diff
- 逐层比较
- 如果是 component,执行 component diff
- 如果是 element,执行 element diff
component diff
- 先看比较双方类型一不一致,不一致直接替换
- 类型相同则更新属性
- 深入组件进行递归 tree diff
element diff
- 先看标签名一不一致,不一致直接替换
- 标签名一致比较属性
- 深入标签进行递归 tree diff