一、前言React和Vue这两个最流行的前端框架都使用了VirtualDOM技术来提高页面渲染效率。那么,什么是虚拟DOM?它是如何提高页面渲染效率的?本系列文章将详细讲解VirtualDOM的创建过程,并实现一个简单的Diff算法来更新页面。本文内容脱离任何前端框架,只谈最纯粹的VirtualDOM。打字太累了,下面的VirtualDOM就用VD来表示。这是VD系列文章的开篇,后续会有更多文章带你深入了解VD的奥秘。2、什么是VD从本质上讲,VD只是一个简单的JS对象,至少包含三个属性:tag、props和children。不同的框架可能对这三个属性的命名略有不同,但表达的意思是一样的。它们是标签名(tag)、属性(props)和子元素对象(children)。以下是一个典型的VD对象示例:{tag:"div",props:{},children:["HelloWorld",{tag:"ul",props:{},children:[{tag:"li",props:{id:1,class:"li-1"},children:["第",1]}]}]}VD和dom对象是一一对应的,上面VD由以下HTML生成:
HelloWorld
一个dom对象,比如li,通过标签(li)、props({id:1,class:"li-1"})和children(["第",1])是三个属性来描述。3、为什么需要VD有了VD,可以达到有效减少页面渲染次数的目的,从而提高渲染效率。我们先来看一下页面的更新一般会经历几个阶段:从上面的例子可以看出,页面的渲染会分为以下三个阶段:JS计算生成渲染树来绘制页面本例中JS计算用了691毫秒,生成渲染树用了578毫秒,绘制用了73毫秒。如果能够有效减少生成渲染树和绘制的时间,那么页面更新的效率也会相应提高。通过VD的对比,我们可以将多个操作合并为一个batch操作,从而减少dom重排的次数,从而缩短生成渲染树和绘制的时间。至于如何基于VD更高效的更新dom,是一个很有意思的话题,以后有机会我会另写一篇介绍。4、如何实现VD与真实DOM的映射下面我们先从如何生成VD说起。借助JSX编译器,可以将文件中的HTML转化为一个函数,然后利用该函数生成VD。看下面的例子:functionrender(){return(HelloWorld
);}这个函数用JSX编译后,会输出如下内容:functionrender(){returnh('div',null,'HelloWorld',h('ul',null,h('li',{id:'1','class':'li-1'},'\u7B2C1'))));}这里的h是一个函数,可以任意命名。这个名字是通过babel配置的://.babelrc文件{"plugins":[["transform-react-jsx",{"pragma":"h"//这里可以配置任何名字}]]}接下来,我们只需要定义h函数构造VD:functionflatten(arr){return[].concat.apply([],arr);}functionh(tag,props,...children){return{tag,props:道具||{},儿童:展平(儿童)||[]};}h函数会传入三个或更多的参数,前两个参数是一个标签名,另一个是属性对象。其他三个参数开头的参数都是children。children元素可能是数组形式,需要对数组进行一级解构。例如:functionrender(){return(- 0 {[1,2,3].map(i=>(
- {i} ))}