22-新增ShapeFlags

130 阅读1分钟

前言

其实ShapeFlags的作用就是把前面的组件类型判断给整合起来,写成一个全局的enum,这样后期维护修改,可以便捷些

实现

新增ShapeFlags.ts

/*
 * @Author: Lin zefan
 * @Date: 2022-04-01 14:00:10
 * @LastEditTime: 2022-04-01 15:53:36
 * @LastEditors: Lin zefan
 * @Description: shapeFlags
 * @FilePath: \mini-vue3\src\shared\ShapeFlags.ts
 *
 */

/**
 * element:vnode.type === string
 * stateful_component:isObject(vnode.type)
 * text_children:vnode.type === string
 * array_children:Array.isArray(children)
 */

export const enum ShapeFlags {
  ELEMENT = "element",
  COMPONENT = "component",
  TEXT_CHILDREN = "text_children",
  ARRAY_CHILDREN = "array_children",
}

新增类型判断

vnode.ts

import { ShapeFlags } from "../shared/ShapeFlags";

export function getShapeFlags(type) {
  return typeof type === "string" ? ShapeFlags.ELEMENT : ShapeFlags.COMPONENT;
}
export function getChildrenShapeFlags(children) {
  return typeof children === "string" || isNumber(children)
    ? ShapeFlags.TEXT_CHILDREN
    : typeof children === "object"
    ? ShapeFlags.ARRAY_CHILDREN
    : "";
}

shared/indes.ts

export function isNumber(value) {
  return typeof value === "number" && !isNaN(value);
}

修改 patch

export function patch(vnode, container, parentComponent) {
  if (!vnode) return;
  const { type } = vnode;

  switch (type) {
    case Fragment:
      processFragment(vnode, container, parentComponent);
      break;
    case TextNode:
      processTextNode(vnode, container);
      break;

    default:
      const shapeFlags = getShapeFlags(type);

      if (shapeFlags === ShapeFlags.COMPONENT) {
        // 是一个Component
        processComponent(vnode, container, parentComponent);
      } else if (shapeFlags === ShapeFlags.ELEMENT) {
        // 是一个element
        processElement(vnode, container, parentComponent);
      }

      break;
  }
}

修改mountElement

element.ts

function mountElement(vnode, container, parentComponent) {
  const { type, props, children } = vnode;
  // 创建根元素、将dom元素挂载到实例
  const el = (vnode.$el = document.createElement(type));
  // 设置行内属性
  for (const key in props) {
    const val = props[key];
    /** 注册事件
     * 1. 判断是否on开头并包含一个大写字母开头
     * 2. 是的话,截取on后面的内容
     * 3. 注册元素事件
     */
    if (isEvents(key)) {
      el.addEventListener(isEvents(key), val);
    } else {
      el.setAttribute(key, val);
    }
  }

  const shapeFlags = getChildrenShapeFlags(children);
  // 设置children
  if (shapeFlags === ShapeFlags.TEXT_CHILDREN) {
    el.textContent = children;
  } else if (shapeFlags === ShapeFlags.ARRAY_CHILDREN) {
    mountChildren(children, el, parentComponent);
  }

  container.append(el);
}