perf: micro optimizations for vnode creation
This commit is contained in:
parent
40ccbdeaac
commit
8be578b6b6
@ -88,6 +88,7 @@ export interface VNode<HostNode = any, HostElement = any> {
|
||||
// structure would be stable. This allows us to skip most children diffing
|
||||
// and only worry about the dynamic nodes (indicated by patch flags).
|
||||
const blockStack: (VNode[] | null)[] = []
|
||||
let currentBlock: VNode[] | null = null
|
||||
|
||||
// Open a block.
|
||||
// This must be called before `createBlock`. It cannot be part of `createBlock`
|
||||
@ -101,7 +102,7 @@ const blockStack: (VNode[] | null)[] = []
|
||||
// disableTracking is true when creating a fragment block, since a fragment
|
||||
// always diffs its children.
|
||||
export function openBlock(disableTracking?: boolean) {
|
||||
blockStack.push(disableTracking ? null : [])
|
||||
blockStack.push((currentBlock = disableTracking ? null : []))
|
||||
}
|
||||
|
||||
let shouldTrack = true
|
||||
@ -116,15 +117,20 @@ export function createBlock(
|
||||
patchFlag?: number,
|
||||
dynamicProps?: string[]
|
||||
): VNode {
|
||||
// avoid a block with optFlag tracking itself
|
||||
// avoid a block with patchFlag tracking itself
|
||||
shouldTrack = false
|
||||
const vnode = createVNode(type, props, children, patchFlag, dynamicProps)
|
||||
shouldTrack = true
|
||||
const trackedNodes = blockStack.pop()
|
||||
vnode.dynamicChildren =
|
||||
trackedNodes && trackedNodes.length ? trackedNodes : EMPTY_ARR
|
||||
// a block is always going to be patched
|
||||
trackDynamicNode(vnode)
|
||||
// save current block children on the block vnode
|
||||
vnode.dynamicChildren = currentBlock || EMPTY_ARR
|
||||
// close block
|
||||
blockStack.pop()
|
||||
currentBlock = blockStack[blockStack.length - 1] || null
|
||||
// a block is always going to be patched, so track it as a child of its
|
||||
// parent block
|
||||
if (currentBlock !== null) {
|
||||
currentBlock.push(vnode)
|
||||
}
|
||||
return vnode
|
||||
}
|
||||
|
||||
@ -145,10 +151,10 @@ export function createVNode(
|
||||
if (isReactive(props) || SetupProxySymbol in props) {
|
||||
props = extend({}, props)
|
||||
}
|
||||
if (props.class != null) {
|
||||
props.class = normalizeClass(props.class)
|
||||
let { class: klass, style } = props
|
||||
if (klass != null && !isString(klass)) {
|
||||
props.class = normalizeClass(klass)
|
||||
}
|
||||
let { style } = props
|
||||
if (style != null) {
|
||||
// reactive state objects need to be cloned since they are likely to be
|
||||
// mutated
|
||||
@ -172,8 +178,8 @@ export function createVNode(
|
||||
_isVNode: true,
|
||||
type,
|
||||
props,
|
||||
key: (props && props.key) || null,
|
||||
ref: (props && props.ref) || null,
|
||||
key: (props !== null && props.key) || null,
|
||||
ref: (props !== null && props.ref) || null,
|
||||
children: null,
|
||||
component: null,
|
||||
suspense: null,
|
||||
@ -195,23 +201,17 @@ export function createVNode(
|
||||
// the next vnode so that it can be properly unmounted later.
|
||||
if (
|
||||
shouldTrack &&
|
||||
(patchFlag ||
|
||||
currentBlock !== null &&
|
||||
(patchFlag > 0 ||
|
||||
shapeFlag & ShapeFlags.STATEFUL_COMPONENT ||
|
||||
shapeFlag & ShapeFlags.FUNCTIONAL_COMPONENT)
|
||||
) {
|
||||
trackDynamicNode(vnode)
|
||||
currentBlock.push(vnode)
|
||||
}
|
||||
|
||||
return vnode
|
||||
}
|
||||
|
||||
function trackDynamicNode(vnode: VNode) {
|
||||
const currentBlockDynamicNodes = blockStack[blockStack.length - 1]
|
||||
if (currentBlockDynamicNodes != null) {
|
||||
currentBlockDynamicNodes.push(vnode)
|
||||
}
|
||||
}
|
||||
|
||||
export function cloneVNode(vnode: VNode): VNode {
|
||||
return {
|
||||
_isVNode: true,
|
||||
|
Loading…
Reference in New Issue
Block a user