Web 界面是由DOM树(树的意思是数据结构)构建而成的,当其中一部分改变时,对应某个DOM节点发生了变化。DOM 元素是非常庞大的,一旦对 DOM 进行操作就可能会导致页面重绘或重排,这样将会对页面的性能造成影响,所以为了减少由于重绘或重排造成的性能影响问题,都要尽可能少的去操作DOM节点。
虚拟 DOM
一个能代表 DOM 树的对象,通常含有标签名、标签上的属性、事件监听和子元素以及其他属性
优点
-
减少 DOM 操作:虚拟 DOM 可以把多次操作合并为一次操作;通过DOM diff 可以把多余操作省掉
-
跨平台:不仅可以变成DOM,还可以变成小程序、IOS应用、安卓应用
如何创建虚拟 DOM
React
createElement('div',{className:'red',onClick:()=>{}},[
createElement('span',{},'span1'),
createElement('span',{},'span2'),
]
)
Vue
h('div',{
class:'red',
on:{
click:()=>{}
},
},[
h('span',{},'span1'),
h('span',{},'span2')
]
)
通过 JSX 创建 (推荐)
React
<div className="red" onClcik={fn}>
<span>span1</span>
<span>span2</span>
</div>
Vue
<div className="red"@clcik="fn">
<span>span1</span>
<span>span2</span>
</div>
DOM diff
DOM diff 就是一个函数,我们称之为 patch ,他会对比渲染更新前和更新后的两个虚拟 DOM 对象的差异,形成一个差异补丁,并将其运用到真实的 DOM 上。
DOM diff 的大概逻辑
1.Tree Diff
- 新旧两棵树结构逐层比较,找出那些节点需要更新
- 如果节点是组件就看 Component Diff
- 如果节点是标签或者元素就看 Element Diff
- omponent Diff
- 如果组件类型不同,删除旧内容的内容替换为新内容
- 如果组件类型相同,则只更新属性,然后深入组件做 Tree diff(递归)
- Element Diff
- 如果节点是原生标签,则看标签名做比较,不同直接替换,相同只更新属性
- 然后进入标签后代递归 Tree diff(递归)
DOM diff的问题
没有唯一key值的更新问题
当做动态改变的时候,没有唯一的key值,有可能引起更新错误,因此,不建议使用 :key="index",应该使用:key="id"