<深入浅出Vuejs>虚拟DOM_Vnode

        Vue.js.2.0以后采用了一个中等粒度的解决方案来来更新视图,即引入虚拟DOM.Watcher实例对应到组件级别.即使一个组件中多个节点使用了某个状态,也只有一个Watcher实例在侦测这一状态.当这个状态发生了变化时,只能通知到组件,然后由组件内部通过对比虚拟DOM来确定哪一个节点需要被重新渲染.这是一个比较折中的方案.

        虚拟DOM到视图更新整体运行流程:将模板编译成渲染函数(Render),通过执行渲染函数生成Vnode,将Vnode和OldVnode做对比,最后更新视图.

<深入浅出Vuejs>虚拟DOM_Vnode_第1张图片

        虚拟 DOM主要做了两件事:

  1. 提供与真实DOM节点所对应的Vnode节点
  2. 将虚拟节点与上一次渲染使用的OldVnode做对比(Patch函数),找出需要更新的节点进行DOM操作

Vnode是什么?

        Vnode是虚拟DOM中一个重要的内容,是Vuejs中的一个类,用来实例化不同类型的Vnode实例,这些实例代表了不同类型的DOM元素:

        1.注释节点 2.文本节点 3.元素节点 4.组件节点 5.函数节点 6.克隆节点.

        简单来讲,Vnode可以理解为节点描述对象,描述了怎样去创建一个真实的DOM节点.不同类型的Vnode只是有效属性不同(无效属性会被默认为undefined或false).定义如下:

constructor (
    tag?: string,            //节点名称,如p,ul,li,div
    data?: VNodeData,         // 关于这个节点的data值,包括attrs,style,hook等
    children?: ?Array, // 当前节点的子节点
    text?: string,        // 文本内容
    elm?: Node,           // 真实的dom节点
    context?: Component,  // 当前组件的VUE实例
    componentOptions?: VNodeComponentOptions
  ) {
    this.tag = tag
    this.data = data
    this.children = children
    this.text = text
    this.elm = elm
    this.ns = undefined
    this.context = context
    this.functionalContext = undefined
    this.key = data && data.key
    this.componentOptions = componentOptions
    this.componentInstance = undefined
    this.parent = undefined
    this.raw = false
    this.isStatic = false
    this.isRootInsert = true
    this.isComment = false
    this.isCloned = false
    this.isOnce = false
  }

  // DEPRECATED: alias for componentInstance for backwards compat.
  /* istanbul ignore next */
  get child (): Component | void {
    return this.componentInstance
  }
}

比如我定义了一个Vnode,它的数据结构是:

{
    tag: 'div'
    data: {
            id: 'app',
            class: 'page-box'
          },
    children: [
                 {
                   tag: 'p',
                   text: 'this is demo'
                 }
              ]
}

那么由它所渲染出来的DOM节点就是:

this is demo

克隆节点 :克隆节点将一个Vnode的属性全都复制到一个新的Vnode中.其作用是优化静态节点以及slot Node(插槽节点).因为静态节点的内容不会改变,所以除了首次渲染时需要执行渲染函数来获取Vnode之外,后续都不需要重新渲染生成,所以直接使用克隆节点进行渲染即可.

// optimized shallow clone
// used for static nodes and slot nodes because they may be reused across
// multiple renders, cloning them avoids errors when DOM manipulations rely
// on their elm reference.
export function cloneVNode (vnode: VNode): VNode {
  const cloned = new VNode(
    vnode.tag,
    vnode.data,
    // #7975
    // clone children array to avoid mutating original in case of cloning
    // a child.
    vnode.children && vnode.children.slice(),
    vnode.text,
    vnode.elm,
    vnode.context,
    vnode.componentOptions,
    vnode.asyncFactory
  )
  cloned.ns = vnode.ns
  cloned.isStatic = vnode.isStatic
  cloned.key = vnode.key
  cloned.isComment = vnode.isComment
  cloned.fnContext = vnode.fnContext
  cloned.fnOptions = vnode.fnOptions
  cloned.fnScopeId = vnode.fnScopeId
  cloned.asyncMeta = vnode.asyncMeta
  cloned.isCloned = true
  return cloned
}

PS 克隆节点和被克隆节点唯一的区别就是isCloned属性,克隆节点为True,被克隆节点为False. 

        以上就是关于Vue关于Vnode的主要内容,后续将深入介绍虚拟DOM的实现原理.

        本文章仅为本人学习总结,如果有不足还请各位指出!

你可能感兴趣的:(深入浅出Vuejs学习笔记,vue.js)