diff --git a/src/compiler/codegen/index.js b/src/compiler/codegen/index.js index 17b31e5b510..7b8a1826d7a 100644 --- a/src/compiler/codegen/index.js +++ b/src/compiler/codegen/index.js @@ -86,10 +86,16 @@ export function genElement (el: ASTElement, state: CodegenState): string { } // hoist static sub-trees out -function genStatic (el: ASTElement, state: CodegenState): string { +function genStatic (el: ASTElement, state: CodegenState, once: ?boolean): string { el.staticProcessed = true state.staticRenderFns.push(`with(this){return ${genElement(el, state)}}`) - return `_m(${state.staticRenderFns.length - 1}${el.staticInFor ? ',true' : ''})` + return `_m(${ + state.staticRenderFns.length - 1 + },${ + el.staticInFor ? 'true' : 'false' + },${ + once ? 'true' : 'false' + })` } // v-once @@ -115,7 +121,7 @@ function genOnce (el: ASTElement, state: CodegenState): string { } return `_o(${genElement(el, state)},${state.onceId++},${key})` } else { - return genStatic(el, state) + return genStatic(el, state, true) } } diff --git a/src/core/instance/render-helpers/render-static.js b/src/core/instance/render-helpers/render-static.js index 1236c94792c..d80311e5604 100644 --- a/src/core/instance/render-helpers/render-static.js +++ b/src/core/instance/render-helpers/render-static.js @@ -7,12 +7,19 @@ import { cloneVNode, cloneVNodes } from 'core/vdom/vnode' */ export function renderStatic ( index: number, - isInFor?: boolean + isInFor: boolean, + isOnce: boolean ): VNode | Array { - // static trees can be rendered once and cached on the contructor options - // so every instance shares the same cached trees - const options = this.$options - const cached = options.cached || (options.cached = []) + // render fns generated by compiler < 2.5.4 does not provide v-once + // information to runtime so be conservative + const isOldVersion = arguments.length < 3 + // if a static tree is generated by v-once, it is cached on the instance; + // otherwise it is purely static and can be cached on the shared options + // across all instances. + const renderFns = this.$options.staticRenderFns + const cached = isOldVersion || isOnce + ? (this._staticTrees || (this._staticTrees = [])) + : (renderFns.cached || (renderFns.cached = [])) let tree = cached[index] // if has already-rendered static tree and not inside v-for, // we can reuse the same tree by doing a shallow clone. @@ -22,7 +29,7 @@ export function renderStatic ( : cloneVNode(tree) } // otherwise, render a fresh tree. - tree = cached[index] = options.staticRenderFns[index].call(this._renderProxy, null, this) + tree = cached[index] = renderFns[index].call(this._renderProxy, null, this) markStatic(tree, `__static__${index}`, false) return tree } diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js index d8b6c7e6839..5e042668fd7 100644 --- a/test/unit/modules/compiler/codegen.spec.js +++ b/test/unit/modules/compiler/codegen.spec.js @@ -478,7 +478,7 @@ describe('codegen', () => { // have "inline-template'" assertCodegen( '

hello world

', - `with(this){return _c('my-component',{inlineTemplate:{render:function(){with(this){return _m(0)}},staticRenderFns:[function(){with(this){return _c('p',[_c('span',[_v("hello world")])])}}]}})}` + `with(this){return _c('my-component',{inlineTemplate:{render:function(){with(this){return _m(0,false,false)}},staticRenderFns:[function(){with(this){return _c('p',[_c('span',[_v("hello world")])])}}]}})}` ) // "have inline-template attrs, but not having exactly one child element assertCodegen( @@ -498,7 +498,7 @@ describe('codegen', () => { it('generate static trees inside v-for', () => { assertCodegen( `

`, - `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true)])}))}`, + `with(this){return _c('div',_l((10),function(i){return _c('div',[_m(0,true,false)])}))}`, [`with(this){return _c('p',[_c('span')])}`] ) })