From 94998715822589f6f10443b6dba75f193467845d Mon Sep 17 00:00:00 2001 From: HcySunYang Date: Mon, 5 Oct 2020 23:58:37 +0800 Subject: [PATCH] fix(compiler-core): make v-once work with v-if/else-if/else (#2182) Partial fix for #2035 --- .../__tests__/transforms/vOnce.spec.ts | 19 ++++++++++--- packages/compiler-core/src/ast.ts | 2 +- packages/compiler-core/src/transforms/vIf.ts | 27 +++++++++++++------ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/packages/compiler-core/__tests__/transforms/vOnce.spec.ts b/packages/compiler-core/__tests__/transforms/vOnce.spec.ts index 3983aa96..a18a0947 100644 --- a/packages/compiler-core/__tests__/transforms/vOnce.spec.ts +++ b/packages/compiler-core/__tests__/transforms/vOnce.spec.ts @@ -99,15 +99,26 @@ describe('compiler: v-once transform', () => { expect(generate(root).code).toMatchSnapshot() }) - test('with v-if', () => { - const root = transformWithOnce(`
`) + test('with v-if/else', () => { + const root = transformWithOnce(`

`) expect(root.cached).toBe(1) expect(root.helpers).toContain(SET_BLOCK_TRACKING) expect(root.children[0]).toMatchObject({ type: NodeTypes.IF, - // should cache the entire v-if expression, not just a single branch + // should cache the entire v-if/else-if/else expression, not just a single branch codegenNode: { - type: NodeTypes.JS_CACHE_EXPRESSION + type: NodeTypes.JS_CACHE_EXPRESSION, + value: { + type: NodeTypes.JS_CONDITIONAL_EXPRESSION, + consequent: { + type: NodeTypes.VNODE_CALL, + tag: `"div"` + }, + alternate: { + type: NodeTypes.VNODE_CALL, + tag: `"p"` + } + } } }) }) diff --git a/packages/compiler-core/src/ast.ts b/packages/compiler-core/src/ast.ts index 42c93402..35849833 100644 --- a/packages/compiler-core/src/ast.ts +++ b/packages/compiler-core/src/ast.ts @@ -236,7 +236,7 @@ export interface CompoundExpressionNode extends Node { export interface IfNode extends Node { type: NodeTypes.IF branches: IfBranchNode[] - codegenNode?: IfConditionalExpression + codegenNode?: IfConditionalExpression | CacheExpression //

} export interface IfBranchNode extends Node { diff --git a/packages/compiler-core/src/transforms/vIf.ts b/packages/compiler-core/src/transforms/vIf.ts index 2c003492..00832a9a 100644 --- a/packages/compiler-core/src/transforms/vIf.ts +++ b/packages/compiler-core/src/transforms/vIf.ts @@ -20,7 +20,8 @@ import { IfNode, createVNodeCall, AttributeNode, - locStub + locStub, + CacheExpression } from '../ast' import { createCompilerError, ErrorCodes } from '../errors' import { processExpression } from './transformExpression' @@ -62,13 +63,7 @@ export const transformIf = createStructuralDirectiveTransform( ) as IfConditionalExpression } else { // attach this branch's codegen node to the v-if root. - let parentCondition = ifNode.codegenNode! - while ( - parentCondition.alternate.type === - NodeTypes.JS_CONDITIONAL_EXPRESSION - ) { - parentCondition = parentCondition.alternate - } + const parentCondition = getParentCondition(ifNode.codegenNode!) parentCondition.alternate = createCodegenNodeForBranch( branch, key + ifNode.branches.length - 1, @@ -293,3 +288,19 @@ function isSameKey( } return true } + +function getParentCondition( + node: IfConditionalExpression | CacheExpression +): IfConditionalExpression { + while (true) { + if (node.type === NodeTypes.JS_CONDITIONAL_EXPRESSION) { + if (node.alternate.type === NodeTypes.JS_CONDITIONAL_EXPRESSION) { + node = node.alternate + } else { + return node + } + } else if (node.type === NodeTypes.JS_CACHE_EXPRESSION) { + node = node.value as IfConditionalExpression + } + } +}