Skip to content

Commit e181bff

Browse files
committed
feat(custom-element): support emit with options
In a custom element created via `defineCustomElement`, if the first event argument is an object, it will be used as the options object for the emitted CustomEvent. The entire argument list is still exposed via the CustomEvent's `detail` property. ```js emit('event', { bubbles: true }) ``` close #7605
1 parent 7f2c505 commit e181bff

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

packages/runtime-dom/__tests__/customElement.spec.ts

+17
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ describe('defineCustomElement', () => {
408408
onMousedown: () => {
409409
emit('myEvent', 1) // validate hyphenation
410410
},
411+
onWheel: () => {
412+
emit('my-wheel', { bubbles: true }, 1)
413+
},
411414
})
412415
},
413416
})
@@ -467,6 +470,7 @@ describe('defineCustomElement', () => {
467470
detail: [1],
468471
})
469472
})
473+
470474
// #7293
471475
test('emit in an async component wrapper with properties bound', async () => {
472476
const E = defineCustomElement(
@@ -488,6 +492,19 @@ describe('defineCustomElement', () => {
488492
detail: [1],
489493
})
490494
})
495+
496+
test('emit with options', async () => {
497+
container.innerHTML = `<my-el-emits></my-el-emits>`
498+
const e = container.childNodes[0] as VueElement
499+
const spy = vi.fn()
500+
e.addEventListener('my-wheel', spy)
501+
e.shadowRoot!.childNodes[0].dispatchEvent(new CustomEvent('wheel'))
502+
expect(spy).toHaveBeenCalledTimes(1)
503+
expect(spy.mock.calls[0][0]).toMatchObject({
504+
bubbles: true,
505+
detail: [{ bubbles: true }, 1],
506+
})
507+
})
491508
})
492509

493510
describe('slots', () => {

packages/runtime-dom/src/apiCustomElement.ts

+14-4
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,14 @@ import {
2727
nextTick,
2828
warn,
2929
} from '@vue/runtime-core'
30-
import { camelize, extend, hyphenate, isArray, toNumber } from '@vue/shared'
30+
import {
31+
camelize,
32+
extend,
33+
hyphenate,
34+
isArray,
35+
isPlainObject,
36+
toNumber,
37+
} from '@vue/shared'
3138
import { hydrate, render } from '.'
3239

3340
export type VueElementConstructor<P = {}> = {
@@ -405,9 +412,12 @@ export class VueElement extends BaseClass {
405412

406413
const dispatch = (event: string, args: any[]) => {
407414
this.dispatchEvent(
408-
new CustomEvent(event, {
409-
detail: args,
410-
}),
415+
new CustomEvent(
416+
event,
417+
isPlainObject(args[0])
418+
? extend({ detail: args }, args[0])
419+
: { detail: args },
420+
),
411421
)
412422
}
413423

0 commit comments

Comments
 (0)