虚拟 DOM
# 虚拟 DOM
原生的 JS DOM 操作非常消耗性能,而 React 把真实原生 JS DOM 转换成了 JavaScript 对象。这就是虚拟 Dom(Virtual Dom)
每次数据更新后,重新计算虚拟 DOM
,并和上一次生成的虚拟 DOM
进行对比,对发生变化的部分作批量更新。
<div class="title">
<span>Hello World</span>
<ul>
<li>苹果</li>
<li>橘子</li>
</ul>
</div>
const VirtualDom = {
type: 'div',
props: { class: 'title' },
children: [
{
type: 'span',
children: 'Hello World'
},
{
type: 'ul',
children: [
{ type: 'li', children: '苹果' },
{ type: 'li', children: '橘子' }
]
}
]
}
# diff 算法
React
需要同时维护两棵虚拟 DOM
树:一棵表示当前的 DOM
结构,另一棵在 React
状态变更将要重新渲染时生成。React
通过比较这两棵树的差异,决定是否需要修改 DOM
结构,以及如何修改。这种算法称作 diff
算法。
diff 算法大致执行过程:
diff
算法会对新旧两棵树做深度优先遍历,避免对两棵树做完全比较,因此算法复杂度可以达到 O(n)
。然后给每个节点生成一个唯一的标志:
# Key 机制
当同一层级的某个节点添加了对于其他同级节点唯一的 key
属性,当它在当前层级的位置发生了变化后。diff
算法通过新旧节点比较后,如果发现了 key
值相同的新旧节点,就会执行移动操作(然后依然按原策略深入节点内部的差异对比更新),而不会执行原策略的删除旧节点,创建新节点的操作。这无疑大大提高了 React
性能和渲染效率。
注意事项:key
值在比较之前都会被执行 toString()
操作,所以尽量不要使用 object
类型的值作为 key
,会导致同一层级出现 key
值相同的节点。key
值重复的同一类型的节点或组件很可能出现拷贝重复内部子元素的问题。