mirror of https://github.com/vuejs/core.git
fix(custom-element): ensure proper remount and prevent redundant slot parsing with shadowRoot false (#13201)
close #13199
This commit is contained in:
parent
5179d328d9
commit
1d41d4de7f
|
@ -1226,6 +1226,92 @@ describe('defineCustomElement', () => {
|
||||||
expect(target.innerHTML).toBe(`<span>default</span>`)
|
expect(target.innerHTML).toBe(`<span>default</span>`)
|
||||||
app.unmount()
|
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(
|
||||||
|
`<my-el-parent-shadow-false is-shown="" data-v-app="">` +
|
||||||
|
`<div>` +
|
||||||
|
`<my-el-child-shadow-false data-v-app="">` +
|
||||||
|
`<div>child</div>` +
|
||||||
|
`</my-el-child-shadow-false>` +
|
||||||
|
`</div>` +
|
||||||
|
`</my-el-parent-shadow-false>`,
|
||||||
|
)
|
||||||
|
|
||||||
|
isShown.value = false
|
||||||
|
await nextTick()
|
||||||
|
expect(container.innerHTML).toBe(
|
||||||
|
`<my-el-parent-shadow-false data-v-app=""><!----></my-el-parent-shadow-false>`,
|
||||||
|
)
|
||||||
|
|
||||||
|
isShown.value = true
|
||||||
|
await nextTick()
|
||||||
|
expect(container.innerHTML).toBe(
|
||||||
|
`<my-el-parent-shadow-false data-v-app="" is-shown="">` +
|
||||||
|
`<div>` +
|
||||||
|
`<my-el-child-shadow-false data-v-app="">` +
|
||||||
|
`<div>child</div>` +
|
||||||
|
`</my-el-child-shadow-false>` +
|
||||||
|
`</div>` +
|
||||||
|
`</my-el-parent-shadow-false>`,
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('helpers', () => {
|
describe('helpers', () => {
|
||||||
|
|
|
@ -280,7 +280,8 @@ export class VueElement
|
||||||
// avoid resolving component if it's not connected
|
// avoid resolving component if it's not connected
|
||||||
if (!this.isConnected) return
|
if (!this.isConnected) return
|
||||||
|
|
||||||
if (!this.shadowRoot) {
|
// avoid re-parsing slots if already resolved
|
||||||
|
if (!this.shadowRoot && !this._resolved) {
|
||||||
this._parseSlots()
|
this._parseSlots()
|
||||||
}
|
}
|
||||||
this._connected = true
|
this._connected = true
|
||||||
|
@ -298,8 +299,7 @@ export class VueElement
|
||||||
|
|
||||||
if (!this._instance) {
|
if (!this._instance) {
|
||||||
if (this._resolved) {
|
if (this._resolved) {
|
||||||
this._setParent()
|
this._mount(this._def)
|
||||||
this._update()
|
|
||||||
} else {
|
} else {
|
||||||
if (parent && parent._pendingResolve) {
|
if (parent && parent._pendingResolve) {
|
||||||
this._pendingResolve = parent._pendingResolve.then(() => {
|
this._pendingResolve = parent._pendingResolve.then(() => {
|
||||||
|
|
Loading…
Reference in New Issue