什么是VNode

什么是VNode什么是 VNode 在 vue js 中存在一个 VNode 类 使用它可以实例化不同类型的 vnode 实例 而不同类型的 vnode 实例各自表示不同类型的 DOM 元素 例如 DOM 元素有元素节点 文本节点 注释节点等 vnode 实例也会对应着有元素节点和文本节点和注释节点 VNode 类代码如下 exportdefaul constructor tag data children text elm context componentOpt asyncFac

什么是VNode

在vue.js中存在一个VNode类,使用它可以实例化不同类型的vnode实例,而不同类型的vnode实例各自表示不同类型的DOM元素。

例如,DOM元素有元素节点,文本节点,注释节点等,vnode实例也会对应着有元素节点和文本节点和注释节点。

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.functionalContext = 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 } } 

从上面的代码可以看出,vnode只是一个名字,本质上来说就是一个普通的JavaScript对象,是从VNode类实例化的对象。我们用这个JavaScript对象来描述一个真实DOM元素的话,那么该DOM元素上的所有属性在VNode这个对象上都存在对应得属性。

图中展示了使用vnode创建真实的DOM并渲染到视图的过程。可以得知,vnode和视图是一一对应的。我们可以把vnode理解成JavaScript对象版本的DOM元素。

渲染视图的过程是先创建vnode,然后在使用vnode去生成真实的DOM元素,最后插入到页面渲染视图。

VNode的作用

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

Vue.js目前对状态的侦测策略采用了中等粒度。当状态发生变化时,只通知到组件级别,然后组件内使用虚拟DOM来渲染视图。

如图下所示,当某个状态发生变化时,只通知使用了这个状态的组件。也就是说,只要组件使用的众多状态中有一个发生了变化,那么整个组件就要重新渲染。

变化侦测只通知到组件级别.PNG

如果组件只有一个节点发生了变化,那么重新渲染整个组件的所有节点,很明显会造成很大的性能浪费。因此,对vnode惊醒缓存,并将上一次的缓存和当前创建的vnode对比,只更新有差异的节点就变得很重要。这也是vnode最重要的一个作用。

VNode的类型

vnode有很多不同的类型,有以下几种:

前面介绍了vnode是一个JavaScript对象,不同类型的vnode之间其实属性不同,准确说是有效属性不同。因为当使用VNode类创建一个vnode时,通过参数为实例设置属性时,无效的属性会默认设置为undefined或者false。对于 vnode身上的无效属性,直接忽略就好。

1.注释节点

由于创建注释节点的过程非常简单,所以直接通过代码来介绍它有哪些属性:

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

一个注释节点只有两个有效属性 text 和 isComment。其余属性全是默认undefined或者false。

例如一个真实的注释节点,所对应的vnode是下面的样子:

// 
    { 
    text: "注释节点", isComment: true } 

2.文本节点

文本节点的创建过程也非常简单,代码如下:

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

当文本类型的vnode被创建时,它只有一个text属性:

{ 
    text: "文本节点" } 

3.克隆节点

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

以静态节点为例,当组件内某个状态发生变化后,当前组件会通过虚拟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 = cloneVNodes(vnode.children) } return cloned } 

4.元素节点

元素节点通常会存在以下4中有效属性。

一个真实的元素节点,对应得vnode是下面这样:

 // 

HelloWorld

{ children: [VNode, VNode], context: { ...}, data: { ...}, tag: "p", ... }

5.组件节点

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

一个组件节点,对应得vnode是下面这样:

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

6.函数式节点

 { 
    functionalContext: { 
   ...}, functionalOptions: { 
   ...}, context: { 
   ...}, data: { 
   ...}, tag: "div" } 

总结

VNode是一个类,可以生产不同类型的vnode实例,不同类型的实例表示不同类型的真实DOM。

由于Vue.js对组件采用了虚拟DOM来更新视图,当属性发生变化时,整个组件都要进行重新渲染的操作,但组件内并不是所有的DOM节点都需要更新,所以将vnode缓存并将当前新生成的vnode和缓存的vnode作对比,只对需要更新的部分进行DOM操作可以提升很多的性能。

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/203847.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 下午9:28
下一篇 2026年3月19日 下午9:28


相关推荐

  • LM567鉴频电路设计

    LM567鉴频电路设计LM567 概述编辑 LM567 为通用锁相环电路音调译码器 LM567 的内部电路及详细工作过程非常复杂 具体的可参考 音频 567 芯片详解 这里仅将其基本功能概述如下 当 LM567 的 脚输入幅度 25mV 频率在其带宽内的信号时 脚由高电平变成低电平 脚输出经频率 电压变换的调制信号 如果在器件的 脚输入音频信号 则在 脚输出受 脚输入调制信号调制的调频方波信号 用外接元件独立设定

    2026年3月20日
    2
  • pycharm激活码2021【永久激活】

    (pycharm激活码2021)JetBrains旗下有多款编译器工具(如:IntelliJ、WebStorm、PyCharm等)在各编程领域几乎都占据了垄断地位。建立在开源IntelliJ平台之上,过去15年以来,JetBrains一直在不断发展和完善这个平台。这个平台可以针对您的开发工作流进行微调并且能够提供…

    2022年3月22日
    156
  • PAT准备之2018.7.24

    昨天被我划水滑过去了,今天终于完成了救赎,基本没有划水,一直在认真的学习,今天也做了不少题,发现自己还是有很多知识点薄弱的地方,还是基础不太好吧,以前总觉得自己这些东西都会,结果发现真到自己用的时候,真的是不会。。。唉!这个暑假再把基础知识补一补吧。今天也是做了三道题。如下1007MaximumSubsequenceSum(25)(25分)Givenasequenceo…

    2022年4月9日
    53
  • Centos7离线安装autoconf

    Centos7离线安装autoconf文章目录1.安装步骤1.1安装M41.2安装perl的依赖包perl-Data-Dumper1.3安装autoconf2.安装过程参考1.安装步骤1.1安装M4下载:http://mirrors.kernel.org/gnu/m4/m4-1.4.13.tar.gz拷贝到centos系统上,并解压:tar-xzvfm4-1.4.13.tar.gz到解压目录中:cdm4-1.4.13#配置编译环境./configure–prefix=/usr/local#编

    2022年6月4日
    59
  • 检测死链的工具[通俗易懂]

    检测死链的工具[通俗易懂]
    XenuLinkSleuth:一种很小很强大的检查网站死链接的工具
    在测试网站的过程中,常常需要检查网站里的所有链接是否正常,如果一个个去点击各个页面来测试,不仅让测试人员感到非常枯燥,也浪费时间。举例来说,如果一个门户网站,首页有100个链接,每个二级页面又有50个链接,那么这样简单一算就是5000次点击,一个测试人员每2秒检查一个页面,要花10000秒,约2.8个小时,还不能100%保证所有的页面都check到位,多少会有点担心:是不是有漏掉的。
    这里借用xenul

    2022年7月23日
    9
  • python调用数组里某一个元素_python中数组用法

    python调用数组里某一个元素_python中数组用法##Python数组注意:Python不具有对数组的内置支持,但是可以使用[Python列表](https://www.w3schools.com/python/python_lists.asp)代替。注意:此页面显示了如何将LISTS用作数组,但是,要在Python中使用数组,您必须导入一个库,例如[NumPylibrary](https://www.w3schools.com/python…

    2022年8月13日
    14

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号