操作虚拟dom比直接操作真实dom要快,这似乎已经刻在了大家的脑子里,但实际上不是这样的。
想要更严谨的回答的话,只能说:虚拟dom并不是比原生dom要快,更确切的说,虚拟dom是比操作不当的原生dom快
虚拟dom的真面目
//虚拟DOM的真身
const vNode = {
key:"d", //是否有key,有则显示,无则显示null
props:{
//标签里是否子元素
children:[
{
....,
ref:"null",
type:'p'},
],
onClick:() => {}, //标签上的事件
className:"d-class", //标签上的属性
}
ref:"null",
type:"div"
}
使用真实dom映射后:
<div className="root" key="rootKey" ref="rootRef">
<h1>昨晚上基金全是绿的,只有我的眼睛是红的</h1>
<div className="top" onClick={() => console.log("工资一千五,心比美式苦")}>
<p>今天你站上天台,我卧上轨道,来生我们有说有笑</p>
</div>
</div>
与之对应的虚拟dom:
const VNode = {
//第一层的div节点
key:"rootKey",
props:{
className:"root"
},
//第二层的h1和div节点
children:[
//h1
{
children:"昨晚上基金全是绿的,只有我的眼睛是红的",
type:"h1",
props:{}
},
//div
{
type:"div",
props:{
className:"top",
onClick:() => console.log("工资一千五,心比美式苦")
},
//div下的p标签
children:[
{
type:"p",
children:"今天你站上天台,我卧上轨道,来生我们有说有笑"
}
]
}
],
ref:"rootRef",
type:"div"
}
所谓的虚拟dom,就是我们真实dom在创建的时候,隐藏在真实dom之下和真实dom所对应的一个对象。这个对象,被我们称为虚拟dom
虚拟dom为什么存在
最开始的核心是为了提升开发效率,而非性能提升。
我们使用react、vue之后,我们只需要关注数据的改变,至于dom的一系列动作,在我们的数据改变之后,react、vue会为我们代劳,这极大程度的提升了我们的开发效率,也是react、vue的核心思想和初衷。
至于很多人说虚拟dom操作会比原生dom更快,也不全面。比如,首次渲染或者所有节点都需要进行更新的时候,这个时候采用虚拟dom会比直接操作原生dom多一重构建虚拟dom的动作,会占用更多的内存以及延长渲染时间。
举个例子🌰
首次渲染不采用虚拟dom:
- 浏览器接受绘制指令
- 创建所有节点
首次渲染采用虚拟dom:
- 浏览器接受绘制指令
- 创建虚拟dom
- 创建所有节点
⚠️注意:虚拟dom的存在,并不是免费的,对比新旧虚拟dom树的差异会带来一定的性能开销。
虚拟dom的优势在于我们更新节点的时候,它会检查哪些节点需要更新。尽量复用已有dom,减少dom的删除和创建。并且这些操作我们是可以通过手动操作js底层api实现的。只是我们手动操作会比较费时,这个工作由虚拟dom代劳会让我们开发更快速便捷。
举个例子🌰
在采用虚拟dom时,假设我们有节点A,两个子节点B/C。然后我们删除C,这个时候会有两棵虚拟dom树,一棵是修改前的A->B/C,另一个棵是修改后的A->B/C
diff算法
会对比这两棵树的差异,然后发现A->B没有更改,保留A->B,C被删除了,那么A->B两个节点的删除和创建操作就省略了,拿来即用。
如果不采用虚拟dom的话,使用JQ的模版,我们可能会把A->B/C三个节点全部删除,再全部重新创建,而A->B是没有改动的,它们的创建删除是完全不必要的开销。
框架的意义
不论是react、vue、angular,这些框架本身都是基于原生的基础上创造的。它们,底层还是依赖的js,并不是一门新的语言。在他们的底层逻辑下,我们使用框架做出的一切行为,都会被框架转化为对原生dom的操作。
总结
- 虚拟DOM不一定会比操作原生DOM更快。
- 虚拟DOM的优势在于节点进行改动的时候尽量减少开销
- React从来没说过虚拟DOM会比原生更快。
- 框架的本质是提升开发效率,让我们的注意力更集中于数据