前言
其实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);
}