feat(compiler-core): re-implement v-once to use cache mechanism
This commit is contained in:
@@ -86,7 +86,7 @@ export interface ComponentInternalInstance {
|
||||
accessCache: Data | null
|
||||
// cache for render function values that rely on _ctx but won't need updates
|
||||
// after initialized (e.g. inline handlers)
|
||||
renderCache: Function[] | null
|
||||
renderCache: (Function | VNode)[] | null
|
||||
|
||||
components: Record<string, Component>
|
||||
directives: Record<string, Directive>
|
||||
|
||||
@@ -179,14 +179,10 @@ export function createRenderer<
|
||||
optimized: boolean = false
|
||||
) {
|
||||
// patching & not same type, unmount old tree
|
||||
if (n1 != null) {
|
||||
if (!isSameType(n1, n2)) {
|
||||
anchor = getNextHostNode(n1)
|
||||
unmount(n1, parentComponent, parentSuspense, true)
|
||||
n1 = null
|
||||
} else if (n1.props && n1.props.$once) {
|
||||
return
|
||||
}
|
||||
if (n1 != null && !isSameType(n1, n2)) {
|
||||
anchor = getNextHostNode(n1)
|
||||
unmount(n1, parentComponent, parentSuspense, true)
|
||||
n1 = null
|
||||
}
|
||||
|
||||
const { type, shapeFlag } = n2
|
||||
|
||||
@@ -49,6 +49,7 @@ export { toString } from './helpers/toString'
|
||||
export { toHandlers } from './helpers/toHandlers'
|
||||
export { renderSlot } from './helpers/renderSlot'
|
||||
export { createSlots } from './helpers/createSlots'
|
||||
export { setBlockTracking } from './vnode'
|
||||
export { capitalize, camelize } from '@vue/shared'
|
||||
|
||||
// Internal, for integration with runtime compiler
|
||||
|
||||
@@ -105,7 +105,24 @@ export function openBlock(disableTracking?: boolean) {
|
||||
blockStack.push((currentBlock = disableTracking ? null : []))
|
||||
}
|
||||
|
||||
let shouldTrack = true
|
||||
// Whether we should be tracking dynamic child nodes inside a block.
|
||||
// Only tracks when this value is > 0
|
||||
// We are not using a simple boolean because this value may need to be
|
||||
// incremented/decremented by nested usage of v-once (see below)
|
||||
let shouldTrack = 1
|
||||
|
||||
// Block tracking sometimes needs to be disabled, for example during the
|
||||
// creation of a tree that needs to be cached by v-once. The compiler generates
|
||||
// code like this:
|
||||
// _cache[1] || (
|
||||
// setBlockTracking(-1),
|
||||
// _cache[1] = createVNode(...),
|
||||
// setBlockTracking(1),
|
||||
// _cache[1]
|
||||
// )
|
||||
export function setBlockTracking(value: number) {
|
||||
shouldTrack += value
|
||||
}
|
||||
|
||||
// Create a block root vnode. Takes the same exact arguments as `createVNode`.
|
||||
// A block root keeps track of dynamic nodes within the block in the
|
||||
@@ -118,9 +135,9 @@ export function createBlock(
|
||||
dynamicProps?: string[]
|
||||
): VNode {
|
||||
// avoid a block with patchFlag tracking itself
|
||||
shouldTrack = false
|
||||
shouldTrack--
|
||||
const vnode = createVNode(type, props, children, patchFlag, dynamicProps)
|
||||
shouldTrack = true
|
||||
shouldTrack++
|
||||
// save current block children on the block vnode
|
||||
vnode.dynamicChildren = currentBlock || EMPTY_ARR
|
||||
// close block
|
||||
@@ -200,7 +217,7 @@ export function createVNode(
|
||||
// component doesn't need to update, it needs to persist the instance on to
|
||||
// the next vnode so that it can be properly unmounted later.
|
||||
if (
|
||||
shouldTrack &&
|
||||
shouldTrack > 0 &&
|
||||
currentBlock !== null &&
|
||||
(patchFlag > 0 ||
|
||||
shapeFlag & ShapeFlags.STATEFUL_COMPONENT ||
|
||||
|
||||
Reference in New Issue
Block a user