From 24355de291211efb5c056729a9acc014adafb0f6 Mon Sep 17 00:00:00 2001 From: Kevin Ball Date: Wed, 24 Oct 2018 10:01:29 -0700 Subject: [PATCH] fix(compiler): templates inside v-pre should be rendered to HTML (#8146) close #8041 --- src/compiler/codegen/index.js | 12 +++++++++++- test/unit/modules/compiler/codegen.spec.js | 12 ++++++++++++ test/unit/modules/compiler/parser.spec.js | 9 +++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js index dd2e62b85f..4afc4711c2 100644 --- a/src/compiler/codegen/index.js +++ b/src/compiler/codegen/index.js @@ -18,6 +18,7 @@ export class CodegenState { maybeComponent: (el: ASTElement) => boolean; onceId: number; staticRenderFns: Array; + pre: boolean; constructor (options: CompilerOptions) { this.options = options @@ -29,6 +30,7 @@ export class CodegenState { this.maybeComponent = (el: ASTElement) => !(isReservedTag(el.tag) && !el.component) this.onceId = 0 this.staticRenderFns = [] + this.pre = false } } @@ -58,7 +60,7 @@ export function genElement (el: ASTElement, state: CodegenState): string { return genFor(el, state) } else if (el.if && !el.ifProcessed) { return genIf(el, state) - } else if (el.tag === 'template' && !el.slotTarget) { + } else if (el.tag === 'template' && !el.slotTarget && !state.pre) { return genChildren(el, state) || 'void 0' } else if (el.tag === 'slot') { return genSlot(el, state) @@ -88,7 +90,15 @@ export function genElement (el: ASTElement, state: CodegenState): string { // hoist static sub-trees out function genStatic (el: ASTElement, state: CodegenState): string { el.staticProcessed = true + // Some elements (templates) need to behave differently inside of a v-pre + // node. All pre nodes are static roots, so we can use this as a location to + // wrap a state change and reset it upon exiting the pre node. + const originalPreState = state.pre + if (el.pre) { + state.pre = el.pre + } state.staticRenderFns.push(`with(this){return ${genElement(el, state)}}`) + state.pre = originalPreState return `_m(${ state.staticRenderFns.length - 1 }${ diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js index 126453555f..0758142ed2 100644 --- a/test/unit/modules/compiler/codegen.spec.js +++ b/test/unit/modules/compiler/codegen.spec.js @@ -595,6 +595,18 @@ describe('codegen', () => { expect(res.render).toBe(generatedCode) }) + // #8041 + it('does not squash templates inside v-pre', () => { + const template = '
' + const generatedCode = `with(this){return _m(0)}` + const renderFn = `with(this){return _c('div',{pre:true},[_c('template',[_c('p',[_v("{{msg}}")])])],2)}` + const ast = parse(template, baseOptions) + optimize(ast, baseOptions) + const res = generate(ast, baseOptions) + expect(res.render).toBe(generatedCode) + expect(res.staticRenderFns).toEqual([renderFn]) + }) + it('not specified ast type', () => { const res = generate(null, baseOptions) expect(res.render).toBe(`with(this){return _c("div")}`) diff --git a/test/unit/modules/compiler/parser.spec.js b/test/unit/modules/compiler/parser.spec.js index 5ab0398990..1cdaa3b717 100644 --- a/test/unit/modules/compiler/parser.spec.js +++ b/test/unit/modules/compiler/parser.spec.js @@ -250,6 +250,15 @@ describe('parser', () => { expect(ast.children[0].children[0].text).toBe('{{msg}}') }) + it('v-pre directive should leave template in DOM', () => { + const ast = parse('
', baseOptions) + expect(ast.pre).toBe(true) + expect(ast.attrs[0].name).toBe('id') + expect(ast.attrs[0].value).toBe('"message1"') + expect(ast.children[0].attrs[0].name).toBe('id') + expect(ast.children[0].attrs[0].value).toBe('"template1"') + }) + it('v-for directive basic syntax', () => { const ast = parse('', baseOptions) const liAst = ast.children[0]