一、前言

虚拟DOM概念随着react的诞生而诞生,由facebook提出,其卓越的性能很快得到广大开发者的认可;继react之后vue2.0也在其核心引入了虚拟DOM的概念,本文将以vue2.0使用的snabbdom入手,来介绍虚拟DOM的主要实现原理。

二、虚拟DOM

在开始介绍snabbdom之前我们想来想两个问题,

(1)什么是虚拟DOM?

vdom可以看作是一个使用javascript模拟了DOM结构的树形结构,这个树结构包含整个DOM结构的信息,如下图:

 

可见左边的DOM结构,不论是标签名称还是标签的属性或标签的子集,都会对应在右边的树结构里。

(2)为什么要使用虚拟DOM?

之前使用原生js或者jquery写页面的时候会发现操作DOM是一件非常麻烦的一件事情,往往是DOM标签和js逻辑同时写在js文件里,数据交互时不时还要写很多的input隐藏域,如果没有好的代码规范的话会显得代码非常冗余混乱,耦合性高并且难以维护。

另外一方面在浏览器里一遍又一遍的渲染DOM是非常非常消耗性能的,常常会出现页面卡死的情况;所以尽量减少对DOM的操作成为了优化前端性能的必要手段,vdom就是将DOM的对比放在了js层,通过对比不同之处来选择新渲染DOM节点,从而提高渲染效率。

(3)vdom如何使用?

下面我将使用snabbdom的用法介绍一下vdom的使用。

三、snabbdom

要了解snabbdom的话有必要先去github上先了解下snabbdom: https://github.com/snabbdom/snabbdom

在这里看到官方给的一个example

这里可以看到列出来的两个主要的核心函数,即h()函数和patch()函数,我们先来看下h()函数:

h函数

 

可以看到创建的虚拟DOM树里面的结构在左边的vnode里都有体现,所以现在看来我们的虚拟DOM结构树和snabbdom中的h()函数是完全可以对应起来的,可以通过一个方法将虚拟DOM结构转化成vnode;而上图中newVnode则指的是虚拟DOM树中的数据发生变化之后生成的vnode。

我们在回过头来看patch()函数

patch函数

patch函数的执行分为两个阶段,两次传递的参数都是两个

第一阶段为虚拟dom的第一次渲染,传递的两个参数分别是放真实DOM的container和生成的vnode,此时patch函数的作用是用来将初次生成的真实DOM结构挂载到指定的container上面。

第二阶段传递的两个参数分别为vnode和newVnode,此时patch函数的作用是使用diff算法对比两个参数的差异,进而更新参数变化的DOM节点;

可以发发现h函数和patch函数在cnabbdom中实现vdom到真实DOM的转化起到了至关重要的作用,那么还有一个很重要的环节,patch函数中是怎么样实现对比两个vnode从而实现对真实DOM的更新的呢,这里还要提一下snabbdom的另外一个核心算法,即diff算法。

diff算法

其实在我们日常开发中我们都在接触类似与diff算法的一些软件,比如svn可以看到当前代码和svn服务器上代码的不同之处,再如Beyond Compare这款软件也可以为我们指出两个对比文件的不同之处

但是此处是如何实现对vnode的对比的呢?参考以下代码:

 1 function updateChildren(vnode, newVnode) {      // 创建对比函数
2 var children = vnode.children || []
3 var newChildren = newVnode.children || []
4
5 children.forEach(function(childrenVnode, index) {
6 var newChildVnode = newChildren[index] // 首先拿到对应新的节点
7 if (childrenVnode.tag === newChildVnode.tag) { // 判断节点是否相同
8 updateChilren(childrenVnode, newChildVnode) // 如果相同执行递归,深度对比节点
9 } else {
10 repleaseNode(childrenVnode, newChildVnode) // 如果不同则将旧的节点替换成新的节点
11 }
12 })
13 }
14
15
16 function repleaseNode(vnode, newVnode) { // 节点替换函数
17 var elem = vnode.elem
18 var newEle = createElement(newVnode)
19 }

此处简单的列举了一下diff算法的原理,以上是最简单的对比,更复杂的对比函数包括对节点的增删以及其它的节点逻辑就不一一赘述了,这里最重要的一部分就是递归的使用,才能将vnode进行深度对比。

四、小结

虚拟DOM在目前流行的几大框架中都作为核心的一部分使用,可见其性能的高效,本文只是简单的通过列举vue中使用的snabbdom库做一个简单的剖析,想要更深层次的理解vdom还有很长的路要走,本文如有不当之处,还劳烦路过大佬批评指出。

什么是虚拟DOM的更多相关文章

  1. 虚拟dom与diff算法 分析

    好文集合: 深入浅出React(四):虚拟DOM Diff算法解析 全面理解虚拟DOM,实现虚拟DOM

  2. React虚拟DOM浅析

    在Web开发中,需要将数据的变化实时反映到UI上,这时就需要对DOM进行操作,但是复杂或频繁的DOM操作通常是性能瓶颈产生的原因,为此,React引入了虚拟DOM(Virtual DOM)的机制. 什 ...

  3. React的虚拟DOM

    ReactJs的一大特点就是引进了虚拟dom(Virtual DOM)的概念.为什么我们需要Virtual DOM,Virtual DOM给我们带来了什么优势. 首先我们要了解一下浏览器的工作流. 当 ...

  4. react通过自己的jsx语法将两者放在一起通过虚拟dom来渲染

    目前较为流行的react确实有很多优点,例如虚拟dom,单向数据流状态机的思想.还有可复用组件化的思想等等.加上搭配jsx语法和es6,适应之后开发确实快捷很多,值得大家去一试.其实组件化的思想一直在 ...

  5. 【虚拟DOM】√

    深度剖析:如何实现一个 Virtual DOM 算法 为什么虚拟DOM更优胜一筹 新建树,渲染树,新建新树,对比树(算法),最少dom操作的渲染树

  6. React生命周期和虚拟DOM

    一.虚拟DOM 1.React并不直接操作DOM,React中的render方法,返回一个DOM描述,React能够将这个DOM描述与内存中的表现进行比较,然后以最快的方式更新浏览器 2.React实 ...

  7. [深入react] 4.牛逼闪闪的虚拟DOM

    React.createElement嵌套后的结果就是虚拟dom,虚拟dom听着很高端,其实就是一个json,类似: { type:'div', props:{ className:"box ...

  8. React虚拟DOM具体实现——利用节点json描述还原dom结构

    前两天,帮朋友解决一个问题: ajax请求得到的数据,是一个对象数组,每个对象中,具有三个属性,parentId,id,name,然后根据这个数据生成对应的结构. 刚好最近在看React,并且了解到其 ...

  9. 实现一个简单的虚拟DOM

    现在的流行框架,无论React还是Vue,都采用虚拟DOM. 好处就是,当我们数据变化时,无需像Backbone那样整体重新渲染,而是局部刷新变化部分,如下组件模版: <ul class=&qu ...

  10. 虚拟DOM详解

    虚拟DOM简介 Virtual Dom可以看做一棵模拟了DOM树的JavaScript对象树,其主要是通过vnode,实现一个无状态的组件,当组件状态发生更新时,然后触发Virtual Dom数据的变 ...

随机推荐

  1. OpenStack Heat模板详解

    Heat模板全称为heat orchestration template,简称为HOT. 1 典型Heat模板结构 heat_template_version: 2015-04-30 descript ...

  2. PAT 甲级 1041 Be Unique (20 分)(简单,一遍过)

    1041 Be Unique (20 分)   Being unique is so important to people on Mars that even their lottery is de ...

  3. Kafka管理与监控——broker宕机后无法消费问题

    背景 因磁盘满了,导致kafka所有的服务器全部宕机了,然后重启kafka集群,服务是启动成功了,但有一些报错: broker1: broker2: broker3:一直在刷以下错误信息 虽然报了这些 ...

  4. 怎么用Ubuntu系统制作Ubuntu系统盘

    ubuntu 16 下载地址: http://releases.ubuntu.com/16.04/?_ga=2.211639766.273896083.1564759714-49163328.1564 ...

  5. PHP和MySQL实现的简单Demo

    实现对输入的数据进行保存数据库的操作: index.html: <html lang="en"> <head> <meta charset=" ...

  6. Cognos Framework操作记录

    备注:这是我单位内部的Cognos Framework配置记录,里面涉及的名字等信息在其他使用环境需要进行相应修改. Cognos数据包配置 打开CYFTest项目, 右键点击andwdb的物理视图 ...

  7. 最新javascript自动按比例显示图片,按比例压缩图片显示

    最新javascript自动按比例显示图片,按比例压缩图片显示 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//E ...

  8. 求数值的n次方根

    二分法 float SqrtByBisection(float n) //用二分法 { if(n<0) //小于0的按照你需要的处理 return n; float mid,last; floa ...

  9. WEB前端动态背景集

    本资源是我在源代码网站上发现的,内附几十种背景动态特效,我单独提取出来精品背景特效在此分享,文件里有20多种精品动态效果,本人觉得可用作于个人博客主页背景,登陆页面背景等,有20多个背景特效,非常漂亮 ...

  10. 【ARM-Linux开发】TI AM437x调试WEB CAM

    Rico Board是基于TI AM437x的一款小型学习板,提供的丰富的接口以及资源,能够实现很多有趣的idea,从本周起,开始总共四期的实验教程,帮助玩家们快速上手Rico Board在嵌入式上面 ...