一、vdom是什么?

vdom是虚拟DOM(Virtual DOM)的简称,指的是用JS模拟的DOM结构,将DOM变化的对比放在JS层来做。换而言之,vdom就是JS对象。

如下DOM结构:


 
  • Item1
  •  
  • Item2
  • 复制代码

    映射成虚拟DOM就是这样:

    {
     tag: "ul",
     attrs: {
     id: "list"
     },
     children: [
     {
     tag: "li",
     attrs: { className: "item" },
     children: ["Item1"]
     }, {
     tag: "li",
     attrs: { className: "item" },
     children: ["Item2"]
     }
     ]
    } 
    复制代码

    二、为什么要用vdom?

    现在有一个场景,实现以下需求:

    [
     {
     name: "张三",
     age: "20",
     address: "北京"
     },
     {
     name: "李四",
     age: "21",
     address: "武汉"
     },
     {
     name: "王五",
     age: "22",
     address: "杭州"
     },
    ]
    复制代码

    将该数据展示成一个表格,并且随便修改一个信息,表格也跟着修改。 用jQuery实现如下:

    
    
    
     
     
     
     Document
    
    
     
     改变     复制代码

    这样点击按钮,会有相应的视图变化,但是你审查以下元素,每次改动之后,table标签都得重新创建,也就是说table下面的每一个栏目,不管是数据是否和原来一样,都得重新渲染,这并不是理想中的情况,当其中的一栏数据和原来一样,我们希望这一栏不要重新渲染,因为DOM重绘相当消耗浏览器性能。

    因此我们采用JS对象模拟的方法,将DOM的比对操作放在JS层,减少浏览器不必要的重绘,提高效率。

    当然有人说虚拟DOM并不比真实的DOM快,其实也是有道理的。当上述table中的每一条数据都改变时,显然真实的DOM操作更快,因为虚拟DOM还存在js中diff算法的比对过程。所以,上述性能优势仅仅适用于大量数据的渲染并且改变的数据只是一小部分的情况。

    虚拟DOM更加优秀的地方在于:

    1、它打开了函数式的UI编程的大门,即UI = f(data)这种构建UI的方式。

    2、可以将JS对象渲染到浏览器DOM以外的环境中,也就是支持了跨平台开发,比如ReactNative。

    另外大家可以参考尤大的一些回答: www.zhihu.com/question/31…

    三、使用snabbdom实现vdom

    snabbdom地址:github.com/snabbdom/sn…

    这是一个简易的实现vdom功能的库,相比vue、react,对于vdom这块更加简易,适合我们学习vdom。vdom里面有两个核心的api,一个是h函数,一个是patch函数,前者用来生成vdom对象,后者的功能在于做虚拟dom的比对和将vdom挂载到真实DOM上。

    简单介绍一下这两个函数的用法:

    • h('标签名', {属性}, [子元素])

    • h('标签名', {属性}, [文本])

    • patch(container, vnode) container为容器DOM元素

    • patch(vnode, newVnode)

    现在我们就来用snabbdom重写一下刚才的例子:

    
    
    
     
     
     
     Document