Skip to content

Commit

Permalink
fix(compiler): templates inside v-pre should be rendered to HTML (#8146)
Browse files Browse the repository at this point in the history
close #8041
  • Loading branch information
kball authored and yyx990803 committed Oct 24, 2018
1 parent 61c32cc commit ecac831
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 1 deletion.
12 changes: 11 additions & 1 deletion src/compiler/codegen/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export class CodegenState {
maybeComponent: (el: ASTElement) => boolean;
onceId: number;
staticRenderFns: Array<string>;
pre: boolean;

constructor (options: CompilerOptions) {
this.options = options
Expand All @@ -29,6 +30,7 @@ export class CodegenState {
this.maybeComponent = (el: ASTElement) => !(isReservedTag(el.tag) && !el.component)
this.onceId = 0
this.staticRenderFns = []
this.pre = false
}
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
}${
Expand Down
12 changes: 12 additions & 0 deletions test/unit/modules/compiler/codegen.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,18 @@ describe('codegen', () => {
expect(res.render).toBe(generatedCode)
})

// #8041
it('does not squash templates inside v-pre', () => {
const template = '<div v-pre><template><p>{{msg}}</p></template></div>'
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")}`)
Expand Down
9 changes: 9 additions & 0 deletions test/unit/modules/compiler/parser.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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('<div v-pre id="message1"><template id="template1"><p>{{msg}}</p></template></div>', 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('<ul><li v-for="item in items"></li></ul>', baseOptions)
const liAst = ast.children[0]
Expand Down

0 comments on commit ecac831

Please sign in to comment.