自学vue3源码 | Virtual DOM

235 阅读1分钟

Virtual DOM就是用js来描述真实DOM和组件,vue通过Virtual DOM来渲染出真实的页面。

<div class="a" id="b">我是内容</div>

{
  tag:'div',        // 元素标签
  attrs:{           // 属性
    class:'a',
    id:'b'
  },
  text:'我是内容',  // 文本内容
  children:[]       // 子元素
}

这就是一个Virtual DOM的简单例子,但是一个真实DOM的属性要比Virtual DOM多的多。

image.png 一个真实的DOM有这么属性,实际开发中我们去频繁更新DOM肯定会产生性能问题。 Virtual DOM就是用一个js对象来描述一个DOM,相对真实DOM就容易不少了。

export const createVNode = (__DEV__
  ? createVNodeWithArgsTransform
  : _createVNode) as typeof _createVNode

function _createVNode(
  type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,
  props: (Data & VNodeProps) | null = null,
  children: unknown = null,
  patchFlag: number = 0,
  dynamicProps: string[] | null = null,
  isBlockNode = false
): VNode {
    // 确定vnode 是什么类型
  const shapeFlag = isString(type)
    ? ShapeFlags.ELEMENT
    : __FEATURE_SUSPENSE__ && isSuspense(type)
      ? ShapeFlags.SUSPENSE
      : isTeleport(type)
        ? ShapeFlags.TELEPORT
        : isObject(type)
          ? ShapeFlags.STATEFUL_COMPONENT
          : isFunction(type)
            ? ShapeFlags.FUNCTIONAL_COMPONENT
            : 0
   //创建 vnode     
  const vnode: VNode = {
    __v_isVNode: true,
    __v_skip: true,
    type,
    props,
    key: props && normalizeKey(props),
    ref: props && normalizeRef(props),
    scopeId: currentScopeId,
    slotScopeIds: null,
    children: null,
    component: null,
    suspense: null,
    ssContent: null,
    ssFallback: null,
    dirs: null,
    transition: null,
    el: null,
    anchor: null,
    target: null,
    targetAnchor: null,
    staticCount: 0,
    shapeFlag,
    patchFlag,
    dynamicProps,
    dynamicChildren: null,
    appContext: null
  }
  // 标准化子节点(通过翻译函数名)
  normalizeChildren(vnode, children)

  return vnode
}

上面就是创建vnode的过程,先确定vnode的类型,创建vnode对象,标准化子节点。