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