diff --git a/flow/component.js b/flow/component.js index 76efebba..cce6b73a 100644 --- a/flow/component.js +++ b/flow/component.js @@ -52,7 +52,7 @@ declare interface Component { _isVue: true; _self: Component; _renderProxy: Component; - _renderParent: ?Component; + _renderContext: ?Component; _watcher: Watcher; _watchers: Array; _data: Object; diff --git a/src/core/instance/lifecycle.js b/src/core/instance/lifecycle.js index 13ffee30..fcd3f75a 100644 --- a/src/core/instance/lifecycle.js +++ b/src/core/instance/lifecycle.js @@ -141,7 +141,7 @@ export function lifecycleMixin (Vue: Class) { } // resolve slots + force update if has children if (hasChildren) { - vm.$slots = resolveSlots(renderChildren) + vm.$slots = resolveSlots(renderChildren, vm._renderContext) vm.$forceUpdate() } } diff --git a/src/core/instance/render.js b/src/core/instance/render.js index 618d4327..1a5e004a 100644 --- a/src/core/instance/render.js +++ b/src/core/instance/render.js @@ -14,7 +14,8 @@ export function initRender (vm: Component) { vm.$vnode = null // the placeholder node in parent tree vm._vnode = null // the root of the child tree vm._staticTrees = null - vm.$slots = resolveSlots(vm.$options._renderChildren) + vm._renderContext = vm.$options._parentVnode && vm.$options._parentVnode.context + vm.$slots = resolveSlots(vm.$options._renderChildren, vm._renderContext) // bind the public createElement fn to this instance // so that we get proper render context inside it. vm.$createElement = bind(createElement, vm) @@ -215,7 +216,8 @@ export function renderMixin (Vue: Class) { } export function resolveSlots ( - renderChildren: ?VNodeChildren + renderChildren: ?VNodeChildren, + context: ?Component ): { [key: string]: Array } { const slots = {} if (!renderChildren) { @@ -226,8 +228,10 @@ export function resolveSlots ( let name, child for (let i = 0, l = children.length; i < l; i++) { child = children[i] - if (child.data && (name = child.data.slot)) { - delete child.data.slot + // named slots should only be respected if the vnode was rendered in the + // same context. + if (child.context === context && + child.data && (name = child.data.slot)) { const slot = (slots[name] || (slots[name] = [])) if (child.tag === 'template') { slot.push.apply(slot, child.children) diff --git a/src/core/vdom/create-component.js b/src/core/vdom/create-component.js index 59d9a9d2..f9642e01 100644 --- a/src/core/vdom/create-component.js +++ b/src/core/vdom/create-component.js @@ -5,7 +5,8 @@ import VNode from './vnode' import { normalizeChildren } from './helpers' import { activeInstance, callHook } from '../instance/lifecycle' import { resolveSlots } from '../instance/render' -import { warn, isObject, hasOwn, hyphenate, validateProp } from '../util/index' +import { createElement } from './create-element' +import { warn, isObject, hasOwn, hyphenate, validateProp, bind } from '../util/index' const hooks = { init, prepatch, insert, destroy } const hooksToMerge = Object.keys(hooks) @@ -101,13 +102,13 @@ function createFunctionalComponent ( } return Ctor.options.render.call( null, - context.$createElement, + bind(createElement, { _self: Object.create(context) }), { props, data, parent: context, children: normalizeChildren(children), - slots: () => resolveSlots(children) + slots: () => resolveSlots(children, context) } ) } diff --git a/test/unit/features/component/component-slot.spec.js b/test/unit/features/component/component-slot.spec.js index 2908eedc..ed4d2920 100644 --- a/test/unit/features/component/component-slot.spec.js +++ b/test/unit/features/component/component-slot.spec.js @@ -372,6 +372,7 @@ describe('Component slot', () => { ` } + const vm = new Vue({ template: 'foo', components: {