mirror of https://github.com/vuejs/core.git
fix(custom-elements): fix event emitting for async custom elements (#5601)
fix #5599
This commit is contained in:
parent
0b39e46192
commit
665f2ae121
|
@ -211,13 +211,16 @@ export function defineAsyncComponent<
|
|||
|
||||
function createInnerComp(
|
||||
comp: ConcreteComponent,
|
||||
{
|
||||
vnode: { ref, props, children, shapeFlag },
|
||||
parent
|
||||
}: ComponentInternalInstance
|
||||
parent: ComponentInternalInstance
|
||||
) {
|
||||
const { ref, props, children, ce } = parent.vnode
|
||||
const vnode = createVNode(comp, props, children)
|
||||
// ensure inner component inherits the async wrapper's ref owner
|
||||
vnode.ref = ref
|
||||
// pass the custom element callback on to the inner comp
|
||||
// and remove it from the async wrapper
|
||||
vnode.ce = ce
|
||||
delete parent.vnode.ce
|
||||
|
||||
return vnode
|
||||
}
|
||||
|
|
|
@ -136,14 +136,6 @@ function reload(id: string, newComp: HMRComponent) {
|
|||
// components to be unmounted and re-mounted. Queue the update so that we
|
||||
// don't end up forcing the same parent to re-render multiple times.
|
||||
queueJob(instance.parent.update)
|
||||
// instance is the inner component of an async custom element
|
||||
// invoke to reset styles
|
||||
if (
|
||||
(instance.parent.type as ComponentOptions).__asyncLoader &&
|
||||
instance.parent.ceReload
|
||||
) {
|
||||
instance.parent.ceReload((newComp as any).styles)
|
||||
}
|
||||
} else if (instance.appContext.reload) {
|
||||
// root instance mounted via createApp() has a reload method
|
||||
instance.appContext.reload()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {
|
||||
defineAsyncComponent,
|
||||
defineComponent,
|
||||
defineCustomElement,
|
||||
h,
|
||||
inject,
|
||||
|
@ -227,7 +228,7 @@ describe('defineCustomElement', () => {
|
|||
})
|
||||
|
||||
describe('emits', () => {
|
||||
const E = defineCustomElement({
|
||||
const CompDef = defineComponent({
|
||||
setup(_, { emit }) {
|
||||
emit('created')
|
||||
return () =>
|
||||
|
@ -241,6 +242,7 @@ describe('defineCustomElement', () => {
|
|||
})
|
||||
}
|
||||
})
|
||||
const E = defineCustomElement(CompDef)
|
||||
customElements.define('my-el-emits', E)
|
||||
|
||||
test('emit on connect', () => {
|
||||
|
@ -277,6 +279,26 @@ describe('defineCustomElement', () => {
|
|||
expect(spy1).toHaveBeenCalledTimes(1)
|
||||
expect(spy2).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
test('emit from within async component wrapper', async () => {
|
||||
const E = defineCustomElement(
|
||||
defineAsyncComponent(
|
||||
() => new Promise<typeof CompDef>(res => res(CompDef as any))
|
||||
)
|
||||
)
|
||||
customElements.define('my-async-el-emits', E)
|
||||
container.innerHTML = `<my-async-el-emits></my-async-el-emits>`
|
||||
const e = container.childNodes[0] as VueElement
|
||||
const spy = jest.fn()
|
||||
e.addEventListener('my-click', spy)
|
||||
// this feels brittle but seems necessary to reach the node in the DOM.
|
||||
await customElements.whenDefined('my-async-el-emits')
|
||||
e.shadowRoot!.childNodes[0].dispatchEvent(new CustomEvent('click'))
|
||||
expect(spy).toHaveBeenCalled()
|
||||
expect(spy.mock.calls[0][0]).toMatchObject({
|
||||
detail: [1]
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('slots', () => {
|
||||
|
|
|
@ -341,15 +341,10 @@ export class VueElement extends BaseClass {
|
|||
this._styles.length = 0
|
||||
}
|
||||
this._applyStyles(newStyles)
|
||||
// if this is an async component, ceReload is called from the inner
|
||||
// component so no need to reload the async wrapper
|
||||
if (!(this._def as ComponentOptions).__asyncLoader) {
|
||||
// reload
|
||||
this._instance = null
|
||||
this._update()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const dispatch = (event: string, args: any[]) => {
|
||||
this.dispatchEvent(
|
||||
|
|
Loading…
Reference in New Issue