美文网首页
认识vue虚拟DOM(二)

认识vue虚拟DOM(二)

作者: 打静爵 | 来源:发表于2019-06-23 22:28 被阅读0次

什么是vnode

在vue中,存在一个VNode类,使用它可以实例化不同类型的vnode实例,不同类型的vnode实例各自表示不同类型的DOM元素。
例如,DOM元素有元素节点,文本节点和注释节点等,vnode实例就对应着元素节点,文本节点等信息。

export default class VNode {
    constructor (tag, data, children, text, elm, context, componentOptions, asyncFactory) {
        this.tag = tag
        this.data = data
        this.children = children
        this.elm = elm
        this.ns = undefined
        this.context = this.context
        this.functionalContext = undefined
        this.functionalScopeId = undefined
        this.functionalOptions = 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
        this.asyncFactory = asyncFactory
        this.asyncMeta = undefined
        this.isAsyncPlaceholder = false
    }
    get child () {
        return this.componentInstance
    }
}

从上面代码可以看到,vnode是从VNode实例化的一个普通的JavaScript对象,用这个对象来描述一个真实DOM元素的话,那么该DOM元素上所有的属性在VNode对象上存在对应的属性。

简单的说,vnode可以理解成节点描述对象,她描述了应该怎样去创建真实的DOM节点。


vnode创建DOM并插入到视图

VNode的作用

由于每次渲染视图都是先创建vnode,然后使用它创建真实DOM插入到页面中,所以可以将上一次渲染视图时所创建的vnode缓存起来,之后每当需要重新渲染视图时,将新创建的vnode和上一次缓存的vnode对比,查看它们之间的不同地方,找出这些不同点再去修改真实DOM。
vue目前对状态的侦测策略采用了中等粒度。


变化侦测通知到组件级别

如图,当某个状态发生改变时,只通知到组件级别,然后组件内使用虚拟DOM来渲染视图,也就是说组件中众多状态中有一个发生变化,那么整个组件就要重新渲染,很明显这样会造成很大的性能浪费。所以,vnode进行缓存并和当前新建的vnode进行对比,只更新变化的节点就显得尤为重要。

VNode类型

vnode的类型有以下几种:
1、 注释节点
2、 文本节点
3、 元素节点
4、 组件节点
5、 函数式组件
6、 克隆节点
当使用VNode类创建一个vnode时,通过参数为实例设置属性时,无效的属性会默认被赋值为undefined或者false,所以下面只讨论vnode有哪些有效属性。

注释节点:
由于创建注释节点过程简单,直接代码说明它的属性:

export const createEmptyVNode = text => {
    const node = new VNode()
    node.text = text
    node.isComment = true
    return node
}

可以看到,一个注释节点只有两个有效属性:text和isComment,其余默认undefined或者false
例如,一个真实的注释节点:

<!--    注释节点  -->

所对应的vnode如下:

text: '注释节点',
isComment: true

文本节点:
当文本类型被创建时,有个一个text属性:

{
  text: 'hello, world'
}

克隆节点:
克隆节点是将现有节点的属性复制到新的节点中,让新创建的节点和被克隆节点属性保持一致,它的作用是优化静态节点和插槽节点。
以静态节点为例,当组件的某个状态发生变化后 ,当前组件会通过虚拟DOM重新渲染视图,静态节点因为它的内容不会改变,所以除了首次渲染需要执行渲染函数获取vnode外,后续更新不需要执行渲染函数重新生成vnode,此时会使用创建克隆节点的方法将vnode克隆一份,使用克隆节点进行渲染,这样就不需要重新执行渲染函数生成新的静态节点的vnode,从而提升一定的性能。

export function cloneVNode (vnode, deep) {
    const cloned = new VNode () {
        vnode.tag,
        vnode.data,
        vnode.children,
        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.isCloned = true
    if (deep && vnode.children) {
        cloned.children = cloneVNode(vnode.children)
    }
}

可以看到,克隆现有节点时,只需要将现有节点属性复制到新的节点即可。克隆节点和被克隆节点之间唯一区别是isCloned属性,克隆节点的isCloned为true,被克隆的原始节点为false

元素节点:
元素节点通常有以下4个有效属性:
tag:节点名称
data: 该属性包含了一些节点上的数据,比如attrs, class和style等
children: 字节点列表
context: 当前组件vue实例
例如,一个真实元素节点:

<p><span>hello</span><span>world</span></p>
{
  children: [VNode, VNode],
  context: {...},
  data: {...},
  tag: 'p',
  ...
}

组件节点:
组件节点和元素节点类似,但有两个独有属性:
componentOptions: 组件节点的选项参数,其中包含propsData、tag和children等信息。
componentInstance: 组件实例

函数式组件:
有两个独有属性:
functionalContext和functionalOptions
通常一个函数组件vnode如下:

{
 componentInstance: {...},
 componentOptions: {...},
 context: {...},
 data: {...},
 tag: 'div'
}

总结

VNode是一个类,可以生成不容类型的vnode实例,对应不同类型的真实DOM元素。
由于vue采用了虚拟DOM更新视图,当属性变化时,整个组件都要进行重新渲染的操作,但组件内并不是所有DOM节点都要更新,所以将vnode缓存并将新生成的vnode进行对比,只更新变化部分以提升性能。

相关文章

  • 【vue3源码】十二、认识虚拟DOM

    【vue3源码】十二、认识虚拟DOM 什么是虚拟DOM? 虚拟DOM(也可以称为vnode)描述了一个真实的DOM...

  • 认识vue虚拟DOM(二)

    什么是vnode 在vue中,存在一个VNode类,使用它可以实例化不同类型的vnode实例,不同类型的vnode...

  • 学习笔记(十六)Vue.js源码剖析 - 虚拟DOM

    Vue.js源码剖析 - 虚拟DOM 虚拟DOM概念回顾 什么是虚拟DOM? 虚拟DOM(Virtual DOM)...

  • 2019-11-23

    vue虚拟DOM是什么?vue的虚拟DOM的用法 1、为什么需要虚拟DOM 前面我们从零开始写了一个简单的类Vue...

  • 【Vue】基础(虚拟DOM & 响应式原理)

    虚拟 DOM Vue 通过建立一个虚拟 DOM 来追踪自己要如何改变真实 DOM 在Vue中定义虚拟节点(VNod...

  • vue render函数

    render 函数 虚拟 DOM Vue 通过建立一个虚拟 DOM对真实 DOM 发生的变化保持追踪 Vue.js...

  • 认识vue虚拟DOM(一)

    什么是虚拟DOM 虚拟DOM其实是时代发展的产物。在web早期,网页通常没有现在这么多交互及动画效果,所以没有很多...

  • 认识vue虚拟DOM(三)

    patch介绍 虚拟DOM最核心的部分是patch,它将vnode渲染成真实DOM过程中并不是暴力覆盖原有DOM,...

  • Vue 基础回顾

    Vue 基础结构 h函数:创建虚拟dom render:把h函数创建的虚拟dom返回 $mount:把虚拟dom转...

  • 基于Vue认识虚拟DOM(Virtual DOM)

    Virtual DOM这个概念相信大家不会太陌生,他产生的前提是浏览器中的DOM是很“昂贵”的,为了直观的感受,我...

网友评论

      本文标题:认识vue虚拟DOM(二)

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