diff --git a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts
index 0b3e7f5938a..a6311bd64b2 100644
--- a/packages/runtime-core/__tests__/components/KeepAlive.spec.ts
+++ b/packages/runtime-core/__tests__/components/KeepAlive.spec.ts
@@ -809,7 +809,9 @@ describe('KeepAlive', () => {
__scopeId: 'foo',
render: withId(() => {
return h(KeepAlive, null, {
- default: () => h(views[viewRef.value], { ref: instanceRef })
+ // since the children of the KeepAlive component will not be compiled as slots,
+ // so, the parent's scopeId should be attached to it's children
+ default: withId(() => h(views[viewRef.value], { ref: instanceRef }))
})
})
}
diff --git a/packages/runtime-core/__tests__/helpers/scopeId.spec.ts b/packages/runtime-core/__tests__/helpers/scopeId.spec.ts
index f570c7f0c12..235fdfe6529 100644
--- a/packages/runtime-core/__tests__/helpers/scopeId.spec.ts
+++ b/packages/runtime-core/__tests__/helpers/scopeId.spec.ts
@@ -1,5 +1,12 @@
import { withScopeId } from '../../src/helpers/scopeId'
-import { h, render, nodeOps, serializeInner } from '@vue/runtime-test'
+import {
+ h,
+ render,
+ nodeOps,
+ serializeInner,
+ BaseTransition,
+ KeepAlive
+} from '@vue/runtime-test'
describe('scopeId runtime support', () => {
const withParentId = withScopeId('parent')
@@ -102,4 +109,54 @@ describe('scopeId runtime support', () => {
expect(serializeInner(root)).toBe(`
`)
})
+
+ test("The Transition component should inherit its parent's scopeId", () => {
+ const Child = {
+ __scopeId: 'child',
+ render: withChildId(function(this: any) {
+ return h(BaseTransition, withChildId(() => this.$slots.default()))
+ })
+ }
+ const App = {
+ __scopeId: 'parent',
+ render: withParentId(() => {
+ return h(
+ 'div',
+ h(Child, null, {
+ default: withParentId(() => h('span'))
+ })
+ )
+ })
+ }
+ const root = nodeOps.createElement('div')
+ render(h(App), root)
+ expect(serializeInner(root)).toBe(
+ `
`
+ )
+ })
+
+ test("The KeepAlive component should inherit its parent's scopeId", () => {
+ const Child = {
+ __scopeId: 'child',
+ render: withChildId(function(this: any) {
+ return h(KeepAlive, withChildId(() => this.$slots.default()))
+ })
+ }
+ const App = {
+ __scopeId: 'parent',
+ render: withParentId((ctx: any) => {
+ return h(
+ 'div',
+ h(Child, null, {
+ default: withParentId(() => h('span'))
+ })
+ )
+ })
+ }
+ const root = nodeOps.createElement('div')
+ render(h(App), root)
+ expect(serializeInner(root)).toBe(
+ `
`
+ )
+ })
})
diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts
index 9b142036219..f9971b32e90 100644
--- a/packages/runtime-core/src/component.ts
+++ b/packages/runtime-core/src/component.ts
@@ -87,6 +87,10 @@ export interface ComponentInternalOptions {
* @internal
*/
__scopeId?: string
+ /**
+ * @internal
+ */
+ __inheritScopeId?: boolean
/**
* @internal
*/
diff --git a/packages/runtime-core/src/components/BaseTransition.ts b/packages/runtime-core/src/components/BaseTransition.ts
index 674eb795616..c25af6fed2f 100644
--- a/packages/runtime-core/src/components/BaseTransition.ts
+++ b/packages/runtime-core/src/components/BaseTransition.ts
@@ -113,6 +113,8 @@ const TransitionHookValidator = [Function, Array]
const BaseTransitionImpl = {
name: `BaseTransition`,
+ __inheritScopeId: true,
+
props: {
mode: String,
appear: Boolean,
diff --git a/packages/runtime-core/src/components/KeepAlive.ts b/packages/runtime-core/src/components/KeepAlive.ts
index 6ad53fda72e..5c73595c331 100644
--- a/packages/runtime-core/src/components/KeepAlive.ts
+++ b/packages/runtime-core/src/components/KeepAlive.ts
@@ -70,6 +70,8 @@ const KeepAliveImpl = {
// would prevent it from being tree-shaken.
__isKeepAlive: true,
+ __inheritScopeId: true,
+
props: {
include: [String, RegExp, Array],
exclude: [String, RegExp, Array],
diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts
index bc1d154527b..9d46fe6fd8b 100644
--- a/packages/runtime-core/src/renderer.ts
+++ b/packages/runtime-core/src/renderer.ts
@@ -807,6 +807,15 @@ function baseCreateRenderer(
}
}
+ const getTreeOwnerWithScopeId = (
+ parent: ComponentInternalInstance
+ ): ComponentInternalInstance => {
+ if (parent.type.__inheritScopeId && parent.parent) {
+ return getTreeOwnerWithScopeId(parent.parent)
+ }
+ return parent
+ }
+
const setScopeId = (
el: RendererElement,
scopeId: string | false | null,
@@ -817,13 +826,14 @@ function baseCreateRenderer(
hostSetScopeId(el, scopeId)
}
if (parentComponent) {
- const treeOwnerId = parentComponent.type.__scopeId
+ const treeOwner = getTreeOwnerWithScopeId(parentComponent)
+ const treeOwnerId = treeOwner.type.__scopeId
// vnode's own scopeId and the current patched component's scopeId is
// different - this is a slot content node.
if (treeOwnerId && treeOwnerId !== scopeId) {
hostSetScopeId(el, treeOwnerId + '-s')
}
- let subTree = parentComponent.subTree
+ let subTree = treeOwner.subTree
if (__DEV__ && subTree.type === Fragment) {
subTree =
filterSingleRoot(subTree.children as VNodeArrayChildren) || subTree
diff --git a/packages/runtime-dom/src/components/Transition.ts b/packages/runtime-dom/src/components/Transition.ts
index 2c0248825e5..7caf00ec44d 100644
--- a/packages/runtime-dom/src/components/Transition.ts
+++ b/packages/runtime-dom/src/components/Transition.ts
@@ -43,6 +43,7 @@ export const Transition: FunctionalComponent = (
) => h(BaseTransition, resolveTransitionProps(props), slots)
Transition.displayName = 'Transition'
+Transition.__inheritScopeId = true
const DOMTransitionPropsValidators = {
name: String,
diff --git a/packages/runtime-dom/src/components/TransitionGroup.ts b/packages/runtime-dom/src/components/TransitionGroup.ts
index 16a6aa39ee1..47b95114592 100644
--- a/packages/runtime-dom/src/components/TransitionGroup.ts
+++ b/packages/runtime-dom/src/components/TransitionGroup.ts
@@ -40,6 +40,8 @@ export type TransitionGroupProps = Omit & {
const TransitionGroupImpl = {
name: 'TransitionGroup',
+ __inheritScopeId: true,
+
props: /*#__PURE__*/ extend({}, TransitionPropsValidators, {
tag: String,
moveClass: String