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/
    
  • 相关阅读:
    第二章IntelliJ IDEA 安装目录的核心文件讲解
    第一章首次运行 IntelliJ IDEA 示例
    struts json ajax整理
    关于struts2文件下载
    mybatis深入资料
    MyBatis获取插入记录的自增长字段值
    好久没有更新博客了,今天更新了几篇
    枚举Enum 的常用方法
    angular js中ng-model时间格式化
    input框输入完回车即可查询事件
  • 原文地址:https://www.cnblogs.com/WindrunnerMax/p/13418382.html
Copyright © 2011-2022 走看看