ShapeFlags呢主要是用来做type类型的,主要做的是性能优化,用映射的方式可读性会比较高,这里ShapeFlags使用的是位运算,位运算在其他地方使用起来也是很方便的,最典型的例子就是权限校验,使用位运算会简化很多,性能也要比映射高出不少,但可读性不高,但总得迈出这一步,学习一下位运算
ShapeFlags
ShapeFlags是用来做type类型的,判断场景会比较多,赋值也会很方便
位运算也不难,| 和 & 这两个符号做处理
结合ShapeFlags.ts来看更清晰易解
| 用来赋值
两者为0才为0
0001 | 0010
// 0001
// 0010
// 0000
& 用来判断
两者为1才为1
0001 & 0011
// 0001
// 0011
// 0001
ShapeFlags
export const enum ShapeFlags {
ELEMENT = 1, // -> 0001
STATEFUL_COMPONENT = 1 << 1, // -> 0010
TEXT_CHILDREN = 1 << 2, // -> 0100
ARRAY_CHILDREN = 1 << 3, // -> 1000
}
这里的 << 是移位,1向左移几位,>> 同理
vnode.ts
export function createVNode(type, props?, children?) {
const vnode = {
type,
props,
children,
shapeFlag: getShapeFlag(type), // 创建类型标识
el: null
}
// children
if (typeof children === 'string') {
// 等同于 vnode.shapeFlag = vnode.shapeFlag | ShapeFlags.TEXT_CHILDREN
vnode.shapeFlag |= ShapeFlags.TEXT_CHILDREN // 判断后进行赋值
}
else if (Array.isArray(children)) {
vnode.shapeFlag |= ShapeFlags.ARRAY_CHILDREN
}
return vnode
}
export function getShapeFlag(type) {
return typeof type === 'string'
? ShapeFlags.ELEMENT
: ShapeFlags.STATEFUL_COMPONENT
}
使用的话就特别简单了,把判断、赋值的地方改动一下,运用位运算的方式进行赋值、判断操作
renderer.ts
function patch(vnode: any, container: any) {
const { type, props, children, shapeFlag } = vnode
// 判断vnode是不是一个element
if (shapeFlag & ShapeFlags.ELEMENT) { //使用 & 进行判断结合上文代入
// 处理element
processElement(vnode, container)
} else if (shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
// 处理组件
processComponent(vnode, container)
}
}
function mountElement(vnode: any, container: any) {
const { type, props, children, shapeFlag } = vnode
const el = (vnode.el = document.createElement(type))
// string array<TODO>
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
el.textContent = children
}
else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
mountChildren(vnode, el)
}
for (const key in props) {
const value = props[key]
el.setAttribute(key, value)
}
container.append(el)
}
上文就把之前写的两个判断改为位运算方式进行判断、赋值
结语
位运算在性能方面其实是天花板了,但是因为可读性原因,所以很多人不愿意去使用,对概念不清楚的情况下很容易写出错漏百出的代码,转而使用映射来实现需求,所以如果对性能方面有需求,使用位运算其实是很不错的选择,没有之一。要学习更细节的位运算,还是需要自己去查资料,敲一敲才能够掌握位运算,熟练使用位运算。最后感谢,动动小手🙂