虚拟DOM

作者: cendechen | 来源:发表于2018-05-07 17:31 被阅读0次

    关于虚拟DOM

    如今流行的mvvm框架的开发模式,已经决定jquery时代将不存在,从react到vue,虚拟dom也越来越流行了,关于虚拟dom,这么高大上的名字,该怎么解读。

    理解

    虚拟dom,用通俗通俗易懂的话来说,就是用一个简单的JS对象去映射到dom对象, 对dom操作,都简化成对JS数据源对象的操作,页面中的每一个dom元素,都能通过这个js对象通过树的遍历算法总能找到DOM的引用地址,每一次更新数据,不需要直接去页面选取dom元素,再更新内容,而是可以直接从js对象出发找到该元素的引用,直接update

    实现

    简单的js对象实现

    var mydiv = document.createElement('div');  
    document.body.append(mydiv)
    

    这样全局就一个变量mydiv对这个div的dom的变量的引用
    当然像vue和react,不可能这样来创建元素,这样也太麻烦了,简单理解和封装如下

    function element(target,props,children){
        var el = document.createElement(target);
        for(var i in props){
            el[i] = props[i];
        }
        //生成子树
        if(children.length > 0 ){
            for(var i in children){
                if(typeof children[i] == "string"){
                    el.innerHTML = children[i];
                }else{
                    var cel = element(children[i][0],children[i][1],children[i][2]);
                    el.appendChild(cel)
                }
            }
        }
        return el;
    }
    

    批量创建虚拟dom的Vnode的封装 案例

    更新

    想要的效果就是更新数据,直接映射到虚拟dom,虚拟dom直接映射到网页里面的真实dom

    对上面创建dom的代码就行优化,我们由数据映射到真实dom。
    先定义虚拟dom的数据

    var velement = {
            tag:'div',
            props:{
                className:'app'
            },
            children:[{
                    tag:'div',
                    props:{
                        className:'app-list'
                    },
                     children:['第一个列表']
                    },{
                    tag:'div',
                    props:{
                        className:'app-list'
                    },
                     children:['第二个列表']
                    },{
                    tag:'div',
                    props:{
                        className:'app-list'
                    },
                     children:['第三个列表']
                    }]
        }
    

    这是js对象,一个描述dom结构的数
    经过vNode函数,生成一棵真实的dom树结构


    image.png

    我们更新velement里面的属性,我们怎么让映射到dom上呢

    image.png

    首先需要监听数据的变化。
    此处可以有两种方法

    借助es6 ,object的get和set 回调函数
    数据的subscriber 发布订阅者模式

    再进行树的diff运算,常用的遍历树的算法有两种方法,深度优先遍历和广度优先遍历
    vue用到的diff算法,采用的是深度优先遍历算法

    对新旧两棵树进行一次深度优先遍历,找到每个节点都会有的唯一标记,在遍历时,每一次遍历的一个新树,如果不一样,就记录把在一个对象里面。

    最后一步,根据diff结果,执行更新逻辑

    性能(摘自网上,没有亲自测试)

    image.png

    以上四幅图,以前是 原生操作,JQuery ,VirtualDOM,React,再chrome的timeline中的性能对比,再原图中,我们并没有看出虚拟dom和react 有明显的优势,原生操作是最快的,其他三种方式相差不大 。至少说明没有我们想象的那么好的性能


    image.png

    基于三种方式,测试插入10000个节点 100次和修改3000个节点的100次,分别取这100次的耗时最大值,最小值,和平均值,可以看出来直接原生操作更快

    写在最后

    其实知道了,以上原理,github上有很多实现virtualDOM的项目,可以简单读一下代码。 虚拟DOM

    现在越来越流行的mvvm框架出现,主要是为解决某一类问题,或提高性能?或 提高开发效率?或提高可维护性?亦或是其他用途,往往选择一个框架是解决某一类问题,这样也会在其他方面做出牺牲。

    介于虚拟dom的mvvm框架在如今

    1. 在牺牲一定性能的前提下,对项目的可维护性极大的增强
    2. 真正的开发模式变成了 data->view,开发人用只用关注data层的控制
    3. 让ui开发的可重用性越来越强

    开发模式

    view不会变化或者小范围局部变化的页面(新闻页面,宣传页面 ,H5)
    直接用写html + 原生的js/jquery修改即可

    view整体变化,但是性能要求不要,对重绘和回流不做严格限制
    粗暴有效的方式, 一旦数据发生变化,重绘整个视图,代码构造逻辑简单

    交互复杂,数据状态变化复杂
    借助第三方库vue 来实现可维护性,快速开发

    相关文章

      网友评论

          本文标题:虚拟DOM

          本文链接:https://www.haomeiwen.com/subject/fosvrftx.html