chore(compiler-core): reduce unnecessary cache inside v-once (#4112)
This commit is contained in:
parent
e5a4412764
commit
eca4d7891a
@ -425,6 +425,18 @@ describe('compiler: transform v-model', () => {
|
||||
).not.toBe(NodeTypes.JS_CACHE_EXPRESSION)
|
||||
})
|
||||
|
||||
test('should not cache update handler if it inside v-once', () => {
|
||||
const root = parseWithVModel(
|
||||
'<div v-once><input v-model="foo" /></div>',
|
||||
{
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
}
|
||||
)
|
||||
expect(root.cached).not.toBe(2)
|
||||
expect(root.cached).toBe(1)
|
||||
})
|
||||
|
||||
test('should mark update handler dynamic if it refers slot scope variables', () => {
|
||||
const root = parseWithVModel(
|
||||
'<Comp v-slot="{ foo }"><input v-model="foo.bar"/></Comp>',
|
||||
|
@ -530,6 +530,15 @@ describe('compiler: transform v-on', () => {
|
||||
expect(root.cached).toBe(0)
|
||||
})
|
||||
|
||||
test('should not be cached inside v-once', () => {
|
||||
const { root } = parseWithVOn(`<div v-once><div v-on:click="foo"/></div>`, {
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
})
|
||||
expect(root.cached).not.toBe(2)
|
||||
expect(root.cached).toBe(1)
|
||||
})
|
||||
|
||||
test('inline function expression handler', () => {
|
||||
const { root, node } = parseWithVOn(`<div v-on:click="() => foo()" />`, {
|
||||
prefixIdentifiers: true,
|
||||
|
@ -80,6 +80,13 @@ describe('compiler: v-once transform', () => {
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
// v-once inside v-once should not be cached
|
||||
test('inside v-once', () => {
|
||||
const root = transformWithOnce(`<div v-once><div v-once/></div>`)
|
||||
expect(root.cached).not.toBe(2)
|
||||
expect(root.cached).toBe(1)
|
||||
})
|
||||
|
||||
// cached nodes should be ignored by hoistStatic transform
|
||||
test('with hoistStatic: true', () => {
|
||||
const root = transformWithOnce(`<div><div v-once /></div>`, {
|
||||
|
@ -105,6 +105,7 @@ export interface TransformContext
|
||||
parent: ParentNode | null
|
||||
childIndex: number
|
||||
currentNode: RootNode | TemplateChildNode | null
|
||||
inVOnce: boolean
|
||||
helper<T extends symbol>(name: T): T
|
||||
removeHelper<T extends symbol>(name: T): void
|
||||
helperString(name: symbol): string
|
||||
@ -192,6 +193,7 @@ export function createTransformContext(
|
||||
parent: null,
|
||||
currentNode: root,
|
||||
childIndex: 0,
|
||||
inVOnce: false,
|
||||
|
||||
// methods
|
||||
helper(name) {
|
||||
|
@ -107,6 +107,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||
if (
|
||||
!__BROWSER__ &&
|
||||
context.prefixIdentifiers &&
|
||||
!context.inVOnce &&
|
||||
context.cacheHandlers &&
|
||||
!hasScopeRef(exp, context.identifiers)
|
||||
) {
|
||||
|
@ -70,7 +70,7 @@ export const transformOn: DirectiveTransform = (
|
||||
if (exp && !exp.content.trim()) {
|
||||
exp = undefined
|
||||
}
|
||||
let shouldCache: boolean = context.cacheHandlers && !exp
|
||||
let shouldCache: boolean = context.cacheHandlers && !exp && !context.inVOnce
|
||||
if (exp) {
|
||||
const isMemberExp = isMemberExpression(exp.content)
|
||||
const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content))
|
||||
@ -90,6 +90,8 @@ export const transformOn: DirectiveTransform = (
|
||||
// to scope variables.
|
||||
shouldCache =
|
||||
context.cacheHandlers &&
|
||||
// unnecessary to cache inside v-once
|
||||
!context.inVOnce &&
|
||||
// runtime constants don't need to be cached
|
||||
// (this is analyzed by compileScript in SFC <script setup>)
|
||||
!(exp.type === NodeTypes.SIMPLE_EXPRESSION && exp.constType > 0) &&
|
||||
|
@ -7,12 +7,14 @@ const seen = new WeakSet()
|
||||
|
||||
export const transformOnce: NodeTransform = (node, context) => {
|
||||
if (node.type === NodeTypes.ELEMENT && findDir(node, 'once', true)) {
|
||||
if (seen.has(node)) {
|
||||
if (seen.has(node) || context.inVOnce) {
|
||||
return
|
||||
}
|
||||
seen.add(node)
|
||||
context.inVOnce = true
|
||||
context.helper(SET_BLOCK_TRACKING)
|
||||
return () => {
|
||||
context.inVOnce = false
|
||||
const cur = context.currentNode as ElementNode | IfNode | ForNode
|
||||
if (cur.codegenNode) {
|
||||
cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */)
|
||||
|
Loading…
Reference in New Issue
Block a user