zoukankan      html  css  js  c++  java
  • Vue中虚拟DOM的理解

    Vue中虚拟DOM的理解

    Virtual DOM是一棵以JavaScript对象作为基础的树,每一个节点称为VNode,用对象属性来描述节点,实际上它是一层对真实DOM的抽象,最终可以通过渲染操作使这棵树映射到真实环境上,简单来说Virtual DOM就是一个Js对象,用以描述整个文档。

    描述

    在浏览器中构建页面时需要使用DOM节点描述整个文档。

    <div class="root" name="root">
        <p>1</p>
        <div>11</div>
    </div>
    

    如果使用Js对象去描述上述的节点以及文档,那么便类似于下面的样子,当然这不是Vue中用以描述节点的对象,Vue中用以描述一个节点的对象包括大量属性,例如tagdatachildrentextelmnscontextkeycomponentOptionscomponentInstanceparentrawisStaticisRootInsertisCommentisCloned等等,具体的属性可以参阅Vue源码的/dev/src/core/vdom/vnode.js

    {
        type: "tag",
        tagName: "div",
        attr: {
            className: "root"
            name: "root"
        },
        parent: null,
        children: [{
            type: "tag",
            tagName: "p",
            attr: {},
            parent: {} /* 父节点的引用 */, 
            children: [{
                type: "text",
                tagName: "text",
                parent: {} /* 父节点的引用 */, 
                content: "1"
            }]
        },{
            type: "tag",
            tagName: "div",
            attr: {},
            parent: {} /* 父节点的引用 */, 
            children: [{
                type: "text",
                tagName: "text",
                parent: {} /* 父节点的引用 */, 
                content: "11"
            }]
        }]
    }
    

    Vue中首先会解析template中定义的HTML节点以及组件节点,为render作准备,在解析的过程中会生成_c()_v()等函数,其作为renderHelpers用以创建节点,_v()函数就是用以创建文本节点,而_c()函数就是用以创建VNode节点的,这个函数其实就是Vue中定义的_createElement()函数,通过这个函数来确定创建的是普通节点还是组件节点,具体可以在Vue源码中/dev/src/core/vdom/create-element.js以及/dev/src/core/vdom/create-element.js查阅,当解析完成之后,便能够生成render函数,而当render函数执行后便返回了VNode节点组成的虚拟DOM树,树中的每一颗节点都会存储渲染的时候需要的信息,之后便是通过diff算法以及patch过程的createElmpatchVnode渲染到真实DOM

    if (typeof tag === 'string') {
    let Ctor
    ns = (context.$vnode && context.$vnode.ns) || config.getTagNamespace(tag)
    if (config.isReservedTag(tag)) {
      // platform built-in elements
      if (process.env.NODE_ENV !== 'production' && isDef(data) && isDef(data.nativeOn)) {
        warn(
          `The .native modifier for v-on is only valid on components but it was used on <${tag}>.`,
          context
        )
      }
      vnode = new VNode(
        config.parsePlatformTagName(tag), data, children,
        undefined, undefined, context
      )
    } else if ((!data || !data.pre) && isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {
      // component
      vnode = createComponent(Ctor, data, context, children, tag)
    } else {
      // unknown or unlisted namespaced elements
      // check at runtime because it may get assigned a namespace when its
      // parent normalizes children
      vnode = new VNode(
        tag, data, children,
        undefined, undefined, context
      )
    }
    } else {
    // direct component options / constructor
    vnode = createComponent(tag, data, context, children)
    }
    

    作用

    渲染真实DOM的过程中开销是很大的,例如当有时候修改了某个数据或者属性,如果直接渲染到真实DOM上可能会引起整个DOM树的重绘与回流,而diff算法能够只更新修改的那部分DOM结构而不更新整个DOM,这里需要说明的是操作DOM结构的速度并不慢,而性能消耗主要是在浏览器重绘与回流的操作上。
    当选用diff算法进行部分更新的时候就需要比较旧DOM结构与新DOM结构的不同,此时就需要VNode来描述整个DOM结构,首先根据真实DOM生成Virtual DOM,当Virtual DOM某个节点的数据改变后会生成一个新的Vnode,然后通过newVNodeoldVNode进行对比,发现有不同之处便进行patch修改于真实DOM,然后使旧的Virtual DOM赋值为新的Virtual DOM
    简单来说建立Virtual DOM的目的是减少对于整个DOM的操作,通过建立Virtual DOM来追踪如何改变真实DOM,从而实现更高效地更新节点。
    使用Virtual DOM同样也是有部分缺点,代码更多,体积更大,内存占用增大,对于小量的单一的DOM修改使用虚拟DOM成本反而更高,但是整体来说,使用Virtual DOM是优点远大于缺点的。

    每日一题

    https://github.com/WindrunnerMax/EveryDay
    

    参考

    https://juejin.im/post/6844903607913938951
    https://segmentfault.com/a/1190000018211084
    https://github.com/lihongxun945/myblog/issues/32
    https://cloud.tencent.com/developer/article/1004551
    https://www.cnblogs.com/fundebug/p/vue-virtual-dom.html
    https://blog.csdn.net/u010692018/article/details/78799335/
    
  • 相关阅读:
    739. Daily Temperatures
    556. Next Greater Element III
    1078. Occurrences After Bigram
    1053. Previous Permutation With One Swap
    565. Array Nesting
    1052. Grumpy Bookstore Owner
    1051. Height Checker
    数据库入门及SQL基本语法
    ISCSI的概念
    配置一个IP SAN 存储服务器
  • 原文地址:https://www.cnblogs.com/WindrunnerMax/p/13418382.html
Copyright © 2011-2022 走看看