Vue2源码解析 虚拟节点VNode

目录

1  什么是VNode

2  VNode的作用

3  VNode的类型

3.1  注释节点

3.2  文本节点

3.3  克隆节点

3.4  元素节点

3.5  组件节点

3.6  函数式组件

4  总结


1  什么是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.text = text
        this.elm = elm
        this.ns = undefined
        this.context = context
        this.functionalContent = undefined
        this.functionalOptions = undefined
        this.functionalScopeId = 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
    }
}

本质上其实是js其中一个普通的对象,是从VNode类实例化的对象。我们用这个js对象来描述一个真实dom元素的话,那么该dom元素上的所有属性在vnode这个对象上都存在对应的属性。简单的说,vnode可以理解成节点描述对象

vnode表示一个真实的dom元素,所有真实的dom节点都使用vnode创建并插入到页面中,如下图所示:

2  VNode的作用

由于每次渲染视图时都是先创建vnode,然后使用它创建真实dom插入到页面中,所以可以将上一次渲染视图时所创建的vnode缓存起来,之后每当需要重新渲染视图时,将新创建的vnode和上一次缓存的vnode进行对比,查看它们之间有哪些不一样的地方,找出这些不一样的地方并基于此去修改真实的dom

3  VNode的类型

vnode的类型有以下几种:

        1.注释节点;

        2.文本节点;

        3.元素节点;

        4.组件节点;

        5.函数式组件;

        6.克隆节点;

不同类型的vnode之间其实只是属性不同,准备的说是有效属性不同,无效属性一般赋值为undefined或false。

3.1  注释节点

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

注释节点其实就两个有效属性:text、isComment;

例如:<!--  注释节点  -->

          对应的vnode:

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

3.2  文本节点

export function createTextVNode(val) {
    return new VNode(undefined, undefined, undefined, String(val))
}

文本节点一个有效属性;

{
    text: "Hello World!"
}

3.3  克隆节点

克隆节点是将现有节点的属性复制到新节点中,让新创建的节点和被克隆节点的属性保持一致,从而实现克隆效果。它的作用是优化静态节点和插槽节点(slot  node)。

静态节点为例,当组件内的某个状态发生变化后,当前组件会通知虚拟dom重新渲染视图,静态节点因为它的内容不会变化,所以除了首次渲染需要执行渲染函数获取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
    clone.isCloned = true
    if (deep && vnode.children) {
        clone.children = cloneVNode(vnode.children)
    }
    return cloned
}

克隆节点和被克隆的节点之间唯一的区别是isCloned属性,克隆节点的isCloned为true,被克隆的原始节点的isCloned为false。

3.4  元素节点

元素节点板通常会存在以下4种有效属性:

        tag:节点的名称;

        data:节点上的数据;

        children:当前节点的子节点列表;

        context:当前组件的vue实例;

案例:

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

3.5  组件节点

组件节点和元素节点类似,有以下两个独有的属性:

        1.componentOptions:组件节点的选项参数,其中包含propsData、tag、children等;

        2.componentInstance:组件实例;

案例:

组件:<child></child>

{
    componentInstance: {},
    componentOptions: {},
    context: {},
    data: {},
    tag: 'vue-component-1-child',
    // ...
}

3.6  函数式组件

函数式组件和组件节点类似,它有两个特有的属性funcctionalContext和cuncional-Options;

{
    functionalContext: {},
    functionalOptions: {},
    context: {},
    data: {},
    tag: 'div',
}

4  总结

VNode是一个类,可以生成不同类型的vnode实例,而不同类型的vnode表示不同类型的真实dom元素。

vnode有很多类型,本质上都是从VNode类实例化出的对象,其唯一区别只是属性不同。

注:本文章来自于《深入浅出vue.js》(人民邮电出版社)阅读后的笔记整理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值