胖蔡叨叨叨
你听我说

Vue实现的虚拟Dom

所谓虚拟DOM,就是用一个JS对象来描述一个DOM节点。虚拟DOM的实现可以降低我们对于真实DOM的操作频率,提高页面的操作性能。通过结构化数据来描述真实DOM信息。如下,我们看下真实DOM和虚拟DOM的差异。

DOM与虚拟DOM

通过上述的简单了解,我们来总结下DOM与虚拟DOM在使用上有哪些区别。

1、真实DOM非常庞大,操作耗费性能。

Vue是数据驱动视图的,数据发生变化视图就要随之更新,在更新视图的时候难免要操作DOM,而操作真实DOM是非常耗费性能的,因为浏览器的标准把 DOM 设计的非常复杂,所以一个真正的 DOM元素是非常庞大的。我们通过操作一个dom节点来看下浏览器都做了哪些工作。

代码示例:

const  div = document.createElement('div')
let str = ''
for(const key in div) {
    str += key + ''
}
console.log(str)

如上,通过创建一个div标签可以发现浏览器会创建很多我们看不到的属性数据。

2、虚拟DOM, 可用JS的计算性能来换取操作DOM的性能。

更新视图,操作DOM无法避免,我们能做的就是尽可能少的操作DOM。所以我们不要盲目的去更新视图,而是通过对比数据变化前后的状态,计算出视图中哪些地方需要更新,只更新需要更新的地方,而不需要更新的地方则不更新,这样我们就可以尽可能少的操作DOM了。

我们可以用JS模拟出一个DOM节点,即虚拟DOM节点。当数据发生变化时,我们对比变化前后的虚拟DOM节点,通过DOM-Diff算法计算出需要更新的地方,然后去更新需要更新的视图。这就是虚拟DOM产生的原因以及最大的用途。

3、Vue创建VNode类, 实例化成不同类型的vnode,从而描述不同类型的真实DOM。

如右图,VNode类中包含了描述一个真实DOM节点所需要的一系列属性,如tag表示节点的标签名,text表示节点中包含的文本,children表示该节点包含的子节点等。通过属性之间不同的搭配,就可以描述出各种类型的真实DOM节点。

vnode如何更新?

Vue目前对状态的侦测策略采用了中等粒度,当状态发生变化时,只通知到组件级别,然后组件内使用虚拟DOM来渲染视图。

也就是说,只要组件使用的众多状态中有一个发生了变化,那么整个组件就要重新渲染。如果组件只有一个节点发生了变化,那么重新渲染整个组件的所有节点,很明显会造成大的性能浪费。

因为Vue每次渲染视图时都会先创建vnode,然后使用它创建真实DOM插入到页面中,所以可将上一次渲染视图时所创建的vnode缓存起来,之后每当需要重新渲染视图时,将新创建的vnode和上一次缓存的vnode进行对比,查看他们之间有哪些不一样的地方,找出这些不一样的地方并基于此去修改真实的DOM,这样就可以减少更新,提升性能。

vnode类型

通过不同属性之间的搭配,可以描述出6种类型的节点:

  • 注释节点:描述一个注释节点只需两个属性,分别是:text和isComment。其中text属性表示具体的注释信息,isComment是一个标志,用来标识一个节点是否是注释节点。
<!-- 注释节点 -->
所对应的vnode:
{
    text:'注释节点',
    isComment:true
}
  • 文本节点:文本节点描述起来比注释节点更简单,因为它只需要一个属性,那就是text属性,用来表示具体的文本信息。
一个文本节点:hello World
所对应的vnode:
{
    text:'hello World'
}
  • 组件节点:组件节点和元素节点类似,它除了有元素节点具有的属性之外,它还有下面两个特有的属性:
    • componentOptions : 组件的option选项,如组件的props等
    • componentInstance : 当前组件节点对应的Vue实例
  • 函数式组件节点:函数式组件节点和组件节点类似,相较于组件节点,它又有两个特有的属性。
    • functionalContext :函数式组件对应的Vue实例
    • functionalOptions : 组件的option选项
  • 元素节点:相比之下,元素节点更贴近于我们通常看到的真实DOM节点。元素节点通常会存在以下4种有效属性。
    • Tag:一个节点的名称,例如p、ul、li和div等
    • Data:该属性包含了一些节点上的数据,比如attrs、class和style等。
    • Children: 当前节点的子节点列表。
    • Context: 它是当前组件的Vue.js实例。
  • 克隆节点:克隆节点就是将现有节点的属性复制到新节点中,让新创建的节点和被克隆的节点属性保持一致,从而实现克隆效果。它的作用是优化静态节点和插槽节点,提升性能。克隆节点和被克隆节点之间唯一区别是isClone属性,克隆节点的isClonetrue,被克隆的原始节点的isClonefalse

特点

1、虚拟DOM的运作原理是使用状态生成虚拟节点,然后使用虚拟节点渲染视图。之所以需要先使用状态生成虚拟节点,是因为如果直接用状态生成真实的DOM,会有一定的性能浪费。

2、虚拟DOM在Vue中所做的事就是提供虚拟节点vnode和新旧两个vnode进行比对,并根据比对结果进行DOM操作来更新视图。

3、由于Vue对组件采用了虚拟DOM来更新视图,当属性发生变化时,整个组件都要进行重新渲染操作,但组件内并不是所有DOM节点都需要更新,所以将vnode缓存并将当前新生成的vnode和上一次缓存的oldVnode进行对比,只对需要更新的部分进行DOM操作可以提升很多性能。

赞(0) 打赏
转载请附上原文出处链接:胖蔡叨叨叨 » Vue实现的虚拟Dom
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏