Skip to content

04实现VDOM下的一个VNode节点

什么是Vnode

我们知道,render function会被转化成VNode节点。Virtual DOM其实就是一棵以JS对象(Vnode节点)作为基础的树。用对象属性来描述树节点,实际上它只是一层对真实DOM的抽象。最终可以通过一系列操作使这棵树映射到真实环境上。 由于VDOM是以JS对象为基础不依赖真实平台环境,所以使它具有了跨平台的能力。

实现一个VNode

VNode归根结底就是一个JS对象,只要这个类的一些属性可以正确直观地描述清楚当前节点的信息即可。我们来实现个简单的VNode类,加入一些基本属性,为了便于理解,我们先不考虑复杂的情况。

js
class VNode {
  constructor(tag, data, children, text, elem) {
    this.tag = tag            // 当前节点的标签名
    this.data = data          // 当前节点的一些数据信息,如props,attrs等
    this.children = children  // 当前节点的子节点,为数组
    this.text = text          // 当前节点的文本
    this.elem = elem          // 当前虚拟节点对应的真实DOM节点
  }
}

比如,目前有这个一个Vue组件:

html
<template>
  <span class="demo" v-show="isShow">
    This is a span.
  </span>
</template>

用JS代码形式就是这样的

js
function render() {
  return new VNode(
    'span',
    {
      // 指令集合数组
      directives: [
        {
          // v-show指令
          rawName: 'v-show',
          expression: 'isShow',
          name: 'show',
          value: true
        }
      ],
      // 静态class
      staticClass: 'demo'
    },
    [new VNode(undefined, undefined, undefined, 'this is a span')]
  )
}

看看转换成VNode以后的情况:

js
{
  tag: 'span',
  data: {
    /* 指令集合数组 */
    directives: [
      {
        /* v-show指令 */
        rawName: 'v-show',
        expression: 'isShow',
        name: 'show',
        value: true
      }
    ],
    /* 静态class */
    staticClass: 'demo'
  },
  text: undefined,
  children: [
    /* 子节点是一个文本VNode节点 */
    {
      tag: undefined,
      data: undefined,
      text: 'This is a span.',
      children: undefined
    }
  ]
}

然后我们可以将VNode进一步封装,可以实现一些产生常用VNode的方法

创建一个空节点

js
function createEmptyVNode() {
  const node = new VNode()
  node.text = ''
  return node
}

创建一个文本节点

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

克隆一个VNode节点

js
function cloneVNode(node) {
  const cloneVnode = new VNode(
    node.tag,
    node.data,
    node.children,
    node.text,
    node.elem
  )
  return cloneVnode
}

总的来说,VNode 就是一个 JavaScript 对象,用 JavaScript 对象的属性来描述当前节点的一些状态,用 VNode 节点的形式来模拟一棵 Virtual DOM 树。

注:本节代码参考《实现 Virtual DOM 下的一个 VNode 节点》

共 20 个模块,1301 篇 Markdown 文档。