diff --git a/src/core/instance/render.ts b/src/core/instance/render.ts index e7ad14f0d73..b71125b275d 100644 --- a/src/core/instance/render.ts +++ b/src/core/instance/render.ts @@ -25,7 +25,13 @@ export function initRender(vm: Component) { const parentVnode = (vm.$vnode = options._parentVnode!) // the placeholder node in parent tree const renderContext = parentVnode && (parentVnode.context as Component) vm.$slots = resolveSlots(options._renderChildren, renderContext) - vm.$scopedSlots = emptyObject + vm.$scopedSlots = parentVnode + ? normalizeScopedSlots( + vm.$parent!, + parentVnode.data!.scopedSlots, + vm.$slots + ) + : emptyObject // bind the createElement fn to this instance // so that we get proper render context inside it. // args order: tag, data, children, normalizationType, alwaysNormalize @@ -98,7 +104,7 @@ export function renderMixin(Vue: typeof Component) { const vm: Component = this const { render, _parentVnode } = vm.$options - if (_parentVnode) { + if (_parentVnode && vm._isMounted) { vm.$scopedSlots = normalizeScopedSlots( vm.$parent!, _parentVnode.data!.scopedSlots, diff --git a/test/unit/features/v3/apiSetup.spec.ts b/test/unit/features/v3/apiSetup.spec.ts index 118686366e8..4ae9e739e91 100644 --- a/test/unit/features/v3/apiSetup.spec.ts +++ b/test/unit/features/v3/apiSetup.spec.ts @@ -165,6 +165,9 @@ describe('api: setup context', () => { const Child = { setup(_props: any, { slots }: any) { + // #12672 behavior consistency with Vue 3: should be able to access + // slots directly in setup() + expect(slots.foo()).toBeTruthy() return () => h('div', [...slots.foo(), ...slots.bar()]) } }