Vue.js之VNode的使⽤
什么是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
< = text
this.elm = elm
this.ns = undefined
this.functionalContext = undefined
this.functionalOptions = undefined
this.functionalScopeId = undefined
this.key = data && data.key
thisponentOptions = componentOptions
thisponentInstance = 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 thisponentInstance
}
}
从上⾯的代码可以看出,vnode只是⼀个名字,本质上来说就是⼀个普通的JavaScript对象,是从VNode类实例化的对象。我们⽤这个JavaScript对象来描述⼀个真实DOM元素的话,那么该DOM元素上的所有属性在VNode这个对象上都存在对应得属性。
简单来说,vnode可以理解成节点描述对象,他描述了应该怎样去创建真实的DOM节点。
例如,tag表⽰⼀个元素节点的名称,text表⽰⼀个⽂本节点的⽂本,children表⽰⼦节点等。vnode表⽰⼀个真实的DOM元素,所有真实的DOM节点都是⽤vnode创建并插⼊到页⾯中。
VNode创建DOM并插⼊到视图
图中展⽰了使⽤vnode创建真实的DOM并渲染到视图的过程。可以得知,vnode和视图是⼀⼀对应的。我们可以把vnode理解成JavaScript对象版本的DOM元素。
渲染视图的过程是先创建vnode,然后在使⽤vnode去⽣成真实的DOM元素,最后插⼊到页⾯渲染视图。
VNode的作⽤
由于每次渲染视图时都是先创建vnode,然后使⽤它创建的真实DOM插⼊到页⾯中,所以可以将上⼀次渲染视图时先所创建的vnode先缓存起来,之后每当需要重新渲染视图时,将新创建的vnode和上⼀次缓存的vnode对⽐,查看他们之间有哪些不⼀样的地⽅,出不⼀样的地⽅并基于此去修改真实的DOM。
Vue.js⽬前对状态的侦测策略采⽤了中等粒度。当状态发⽣变化时,只通知到组件级别,然后组件内使⽤虚拟DOM来渲染视图。
如图下所⽰,当某个状态发⽣变化时,只通知使⽤了这个状态的组件。也就是说,只要组件使⽤的众多状态中有⼀个发⽣了变化,那么整个组件就要重新渲染。
如果组件只有⼀个节点发⽣了变化,那么重新渲染整个组件的所有节点,很明显会造成很⼤的性能浪费。因此,对vnode惊醒缓
存,并将上⼀次的缓存和当前创建的vnode对⽐,只更新有差异的节点就变得很重要。这也是vnode最重要的⼀个作⽤。
VNode的类型
vnode有很多不同的类型,有以下⼏种:
注释节点
1. ⽂本节点
2. 元素节点
3. 组件节点
4. 函数式节点
5. 克隆节点
前⾯介绍了vnode是⼀个JavaScript对象,不同类型的vnode之间其实属性不同,准确说是有效属性不同。因为当使⽤VNode类创建⼀个vnode时,通过参数为实例设置属性时,⽆效的属性会默认设置为undefined或者false。对于 vnode⾝上的⽆效属性,直接忽略就好。
1.注释节点
由于创建注释节点的过程⾮常简单,所以直接通过代码来介绍它有哪些属性:
export const createEmptyVNode = text => {
const node = new VNode()
< = 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.克隆节点js获取子元素
克隆节点是将现有节点的属性赋值到新节点中,让新创建的节点和被克隆的节点的属性保持⼀致,从⽽实现克隆效果。它的作⽤是优化静态节点和插槽节点(slot node)。
以静态节点为例,当组件内某个状态发⽣变化后,当前组件会通过虚拟DOM重新渲染视图,静态节点因为它的内容不会改变,所以除了⾸次渲染需要执⾏渲染函数获取vnode之外,后续更新不需要执⾏渲染函数重新⽣成vnode。
因此,这是就会使⽤创建克隆节点的⽅法将vnode克隆⼀份,使⽤克隆节点进⾏渲染。这样就不需要执⾏渲染函数⽣成新的静态节
点的vnode,从⽽提升⼀定的性能。
创建克隆节点的代码如下:
export function cloneVNode(vnode, deep) {
const cloned = new VNode(vnode.tag, vnode.data, vnode.children, , vnode.elm, t, vnodeponentOptions, 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
}
克隆现有节点,只需要将现有节点的属性全部赋值到新节点中。
克隆节点和被克隆节点位移的区别是isCloned属性,克隆节点为true,被克隆的原始节点为false。
4.元素节点
元素节点通常会存在以下4中有效属性。
tag:tag就是⼀个节点的名称,例如 p、ul、li和div等。
data:改属性包含了⼀些节点上的数据,⽐如attrs、class和style等。
children:当前节点的⼦节点列表。
context:它是当前组件的Vue.js实例
⼀个真实的元素节点,对应得vnode是下⾯这样:
// <p><span>Hello</span><span>World</span></p>
{
children: [VNode, VNode],
context: {...},
data: {...},
tag: "p",
...
}
5.组件节点
组件节点和元素节点类似,有以下两个独有的属性。
componentOptions:组件节点的选项参数,其中包含了propsData、tag和children等信息
componentInstance:组件的实例,也就是Vue.js的实例。事实上,在Vue.js中,每个组件都有⼀个Vue.js实例。
⼀个组件节点,对应得vnode是下⾯这样:
// <child></child>
{
componentInstance: {...},
componentOptions: {...},
context: {...},
data: {...},
tag: "vue-component-1-child",
...
}
6.函数式节点
函数式节点和组件节点类似,他有两个独有的属性functionalContext和functionalOptions。
通常,⼀个函数式节点的vnode是下⾯这样:
{
functionalContext: {...},
functionalOptions: {...},
context: {...},
data: {...},
tag: "div"
}
总结
VNode是⼀个类,可以⽣产不同类型的vnode实例,不同类型的实例表⽰不同类型的真实DOM。
由于Vue.js对组件采⽤了虚拟DOM来更新视图,当属性发⽣变化时,整个组件都要进⾏重新渲染的操作,但组件内并不是所有的DOM节点都需要更新,所以将vnode缓存并将当前新⽣成的vnode和缓存的vnode作对⽐,只对需要更新的部分进⾏DOM操作可以提升很多的性能。
vnode有很多类型,它们本质上都是Vnode实例化出的对象,其唯⼀区别是属性不同。
到此这篇关于Vue.js之VNode的使⽤的⽂章就介绍到这了,更多相关VNode使⽤内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。