diff --git a/src/core/instance/lifecycle.js b/src/core/instance/lifecycle.js index 72735305..7863a62f 100644 --- a/src/core/instance/lifecycle.js +++ b/src/core/instance/lifecycle.js @@ -15,6 +15,7 @@ export function initLifecycle (vm) { vm.$children = [] vm.$refs = {} + vm._mounted = false vm._isDestroyed = false vm._isBeingDestroyed = false } @@ -39,7 +40,6 @@ export function lifecycleMixin (Vue) { } } } - this._renderStaticTrees() this._watcher = new Watcher(this, this._render, this._update) this._update(this._watcher.value) this._mounted = true @@ -50,25 +50,10 @@ export function lifecycleMixin (Vue) { return this } - Vue.prototype._renderStaticTrees = function () { - // render static sub-trees for once on mount - const staticRenderFns = this.$options.staticRenderFns - if (staticRenderFns) { - this._staticTrees = new Array(staticRenderFns.length) - for (let i = 0; i < staticRenderFns.length; i++) { - this._staticTrees[i] = staticRenderFns[i].call(this._renderProxy) - } - } - return this - } - Vue.prototype._update = function (vnode) { if (this._mounted) { callHook(this, 'beforeUpdate') } - const parentNode = this.$options._parentVnode - // set vnode parent before patch - vnode.parent = parentNode if (!this._vnode) { // Vue.prototype.__patch__ is injected in entry points // based on the rendering backend used. @@ -77,7 +62,8 @@ export function lifecycleMixin (Vue) { this.$el = this.__patch__(this._vnode, vnode) } this._vnode = vnode - // set parent vnode element after patch + // update parent vnode element after patch + const parentNode = this.$options._parentVnode if (parentNode) { parentNode.elm = this.$el } diff --git a/src/core/instance/render.js b/src/core/instance/render.js index 47d670aa..08e738be 100644 --- a/src/core/instance/render.js +++ b/src/core/instance/render.js @@ -9,7 +9,6 @@ export const renderState = { export function initRender (vm) { vm._vnode = null - vm._mounted = false vm._staticTrees = null vm.$slots = {} // bind the public createElement fn to this instance @@ -26,9 +25,13 @@ export function renderMixin (Vue) { } Vue.prototype._render = function () { + if (!this._mounted) { + // render static sub-trees for once on initial render + renderStaticTrees(this) + } const prev = renderState.activeInstance renderState.activeInstance = this - const { render, _renderChildren } = this.$options + const { render, _renderChildren, _parentVnode } = this.$options // resolve slots. becaues slots are rendered in parent scope, // we set the activeInstance to parent. if (_renderChildren) { @@ -36,6 +39,8 @@ export function renderMixin (Vue) { } // render self const vnode = render.call(this._renderProxy) + // set parent + vnode.parent = _parentVnode // restore render state renderState.activeInstance = prev return vnode @@ -100,6 +105,16 @@ export function renderMixin (Vue) { } } +function renderStaticTrees (vm) { + const staticRenderFns = vm.$options.staticRenderFns + if (staticRenderFns) { + vm._staticTrees = new Array(staticRenderFns.length) + for (let i = 0; i < staticRenderFns.length; i++) { + vm._staticTrees[i] = staticRenderFns[i].call(vm._renderProxy) + } + } +} + function resolveSlots (vm, renderChildren) { if (renderChildren) { const children = flatten(renderChildren()) diff --git a/src/core/vdom/create-component.js b/src/core/vdom/create-component.js index 348436c8..140981c7 100644 --- a/src/core/vdom/create-component.js +++ b/src/core/vdom/create-component.js @@ -70,7 +70,7 @@ export function createComponent (Ctor, data, parent, children, context) { return vnode } -function init (vnode) { +export function createComponentInstanceForVnode (vnode) { const { Ctor, propsData, listeners, parent, children } = vnode.componentOptions const options = { parent, @@ -85,13 +85,12 @@ function init (vnode) { options.render = inlineTemplate.render options.staticRenderFns = inlineTemplate.staticRenderFns } - const child = new Ctor(options) - // if this is a server-rendered mount, - // the vnode would already have an element. - // otherwise the child sets the parent vnode's elm when mounted - // and when updated. - child.$mount(vnode.elm) - vnode.child = child + return new Ctor(options) +} + +function init (vnode) { + const child = vnode.child = createComponentInstanceForVnode(vnode) + child.$mount() } function prepatch (oldVnode, vnode) { diff --git a/src/server/render.js b/src/server/render.js index 271c1b40..9eabe446 100644 --- a/src/server/render.js +++ b/src/server/render.js @@ -1,25 +1,10 @@ +import { createComponentInstanceForVnode } from 'core/vdom/create-component' + export function createRenderFunction (modules, directives, isUnaryTag) { function renderNode (node, write, next, isRoot) { if (node.componentOptions) { - const { Ctor, propsData, listeners, parent, children } = node.componentOptions - const options = { - parent, - propsData, - _parentVnode: node, - _parentListeners: listeners, - _renderChildren: children - } - // check inline-template render functions - const inlineTemplate = node.data.inlineTemplate - if (inlineTemplate) { - options.render = inlineTemplate.render - options.staticRenderFns = inlineTemplate.staticRenderFns - } - const child = new Ctor(options) - child._renderStaticTrees() - const childRoot = child._render() - childRoot.parent = node - renderNode(childRoot, write, next, isRoot) + const child = createComponentInstanceForVnode(node) + renderNode(child._render(), write, next, isRoot) } else { if (node.tag) { renderElement(node, write, next, isRoot)