Skip to content

Commit 9499871

Browse files
authored
fix(compiler-core): make v-once work with v-if/else-if/else (#2182)
Partial fix for #2035
1 parent 752ecee commit 9499871

File tree

3 files changed

+35
-13
lines changed

3 files changed

+35
-13
lines changed

packages/compiler-core/__tests__/transforms/vOnce.spec.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,26 @@ describe('compiler: v-once transform', () => {
9999
expect(generate(root).code).toMatchSnapshot()
100100
})
101101

102-
test('with v-if', () => {
103-
const root = transformWithOnce(`<div v-if="true" v-once />`)
102+
test('with v-if/else', () => {
103+
const root = transformWithOnce(`<div v-if="BOOLEAN" v-once /><p v-else/>`)
104104
expect(root.cached).toBe(1)
105105
expect(root.helpers).toContain(SET_BLOCK_TRACKING)
106106
expect(root.children[0]).toMatchObject({
107107
type: NodeTypes.IF,
108-
// should cache the entire v-if expression, not just a single branch
108+
// should cache the entire v-if/else-if/else expression, not just a single branch
109109
codegenNode: {
110-
type: NodeTypes.JS_CACHE_EXPRESSION
110+
type: NodeTypes.JS_CACHE_EXPRESSION,
111+
value: {
112+
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
113+
consequent: {
114+
type: NodeTypes.VNODE_CALL,
115+
tag: `"div"`
116+
},
117+
alternate: {
118+
type: NodeTypes.VNODE_CALL,
119+
tag: `"p"`
120+
}
121+
}
111122
}
112123
})
113124
})

packages/compiler-core/src/ast.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ export interface CompoundExpressionNode extends Node {
236236
export interface IfNode extends Node {
237237
type: NodeTypes.IF
238238
branches: IfBranchNode[]
239-
codegenNode?: IfConditionalExpression
239+
codegenNode?: IfConditionalExpression | CacheExpression // <div v-if v-once>
240240
}
241241

242242
export interface IfBranchNode extends Node {

packages/compiler-core/src/transforms/vIf.ts

+19-8
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ import {
2020
IfNode,
2121
createVNodeCall,
2222
AttributeNode,
23-
locStub
23+
locStub,
24+
CacheExpression
2425
} from '../ast'
2526
import { createCompilerError, ErrorCodes } from '../errors'
2627
import { processExpression } from './transformExpression'
@@ -62,13 +63,7 @@ export const transformIf = createStructuralDirectiveTransform(
6263
) as IfConditionalExpression
6364
} else {
6465
// attach this branch's codegen node to the v-if root.
65-
let parentCondition = ifNode.codegenNode!
66-
while (
67-
parentCondition.alternate.type ===
68-
NodeTypes.JS_CONDITIONAL_EXPRESSION
69-
) {
70-
parentCondition = parentCondition.alternate
71-
}
66+
const parentCondition = getParentCondition(ifNode.codegenNode!)
7267
parentCondition.alternate = createCodegenNodeForBranch(
7368
branch,
7469
key + ifNode.branches.length - 1,
@@ -293,3 +288,19 @@ function isSameKey(
293288
}
294289
return true
295290
}
291+
292+
function getParentCondition(
293+
node: IfConditionalExpression | CacheExpression
294+
): IfConditionalExpression {
295+
while (true) {
296+
if (node.type === NodeTypes.JS_CONDITIONAL_EXPRESSION) {
297+
if (node.alternate.type === NodeTypes.JS_CONDITIONAL_EXPRESSION) {
298+
node = node.alternate
299+
} else {
300+
return node
301+
}
302+
} else if (node.type === NodeTypes.JS_CACHE_EXPRESSION) {
303+
node = node.value as IfConditionalExpression
304+
}
305+
}
306+
}

0 commit comments

Comments
 (0)