diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts
index df438d47eee..fd8608c916f 100644
--- a/packages/runtime-dom/__tests__/customElement.spec.ts
+++ b/packages/runtime-dom/__tests__/customElement.spec.ts
@@ -1131,6 +1131,92 @@ describe('defineCustomElement', () => {
expect(target.innerHTML).toBe(`default`)
app.unmount()
})
+
+ test('toggle nested custom element with shadowRoot: false', async () => {
+ customElements.define(
+ 'my-el-child-shadow-false',
+ defineCustomElement(
+ {
+ render(ctx: any) {
+ return h('div', null, [renderSlot(ctx.$slots, 'default')])
+ },
+ },
+ { shadowRoot: false },
+ ),
+ )
+ const ChildWrapper = {
+ render() {
+ return h('my-el-child-shadow-false', null, 'child')
+ },
+ }
+
+ customElements.define(
+ 'my-el-parent-shadow-false',
+ defineCustomElement(
+ {
+ props: {
+ isShown: { type: Boolean, required: true },
+ },
+ render(ctx: any, _: any, $props: any) {
+ return $props.isShown
+ ? h('div', { key: 0 }, [renderSlot(ctx.$slots, 'default')])
+ : null
+ },
+ },
+ { shadowRoot: false },
+ ),
+ )
+ const ParentWrapper = {
+ props: {
+ isShown: { type: Boolean, required: true },
+ },
+ render(ctx: any, _: any, $props: any) {
+ return h('my-el-parent-shadow-false', { isShown: $props.isShown }, [
+ renderSlot(ctx.$slots, 'default'),
+ ])
+ },
+ }
+
+ const isShown = ref(true)
+ const App = {
+ render() {
+ return h(ParentWrapper, { isShown: isShown.value } as any, {
+ default: () => [h(ChildWrapper)],
+ })
+ },
+ }
+ const container = document.createElement('div')
+ document.body.appendChild(container)
+ const app = createApp(App)
+ app.mount(container)
+ expect(container.innerHTML).toBe(
+ `` +
+ `` +
+ `
` +
+ `child
` +
+ `` +
+ `
` +
+ ``,
+ )
+
+ isShown.value = false
+ await nextTick()
+ expect(container.innerHTML).toBe(
+ ``,
+ )
+
+ isShown.value = true
+ await nextTick()
+ expect(container.innerHTML).toBe(
+ `` +
+ `` +
+ `
` +
+ `child
` +
+ `` +
+ `
` +
+ ``,
+ )
+ })
})
describe('helpers', () => {
diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts
index aeeaeec9b9f..e65eef77204 100644
--- a/packages/runtime-dom/src/apiCustomElement.ts
+++ b/packages/runtime-dom/src/apiCustomElement.ts
@@ -280,7 +280,8 @@ export class VueElement
// avoid resolving component if it's not connected
if (!this.isConnected) return
- if (!this.shadowRoot) {
+ // avoid re-parsing slots if already resolved
+ if (!this.shadowRoot && !this._resolved) {
this._parseSlots()
}
this._connected = true
@@ -298,8 +299,7 @@ export class VueElement
if (!this._instance) {
if (this._resolved) {
- this._setParent()
- this._update()
+ this._mount(this._def)
} else {
if (parent && parent._pendingResolve) {
this._pendingResolve = parent._pendingResolve.then(() => {