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
This commit is contained in:
Evan You 2024-08-03 13:46:58 +08:00
parent 7f2c505f92
commit e181bff6dc
No known key found for this signature in database
GPG Key ID: 00E9AB7A6704CE0A
2 changed files with 31 additions and 4 deletions

View File

@ -408,6 +408,9 @@ describe('defineCustomElement', () => {
onMousedown: () => {
emit('myEvent', 1) // validate hyphenation
},
onWheel: () => {
emit('my-wheel', { bubbles: true }, 1)
},
})
},
})
@ -467,6 +470,7 @@ describe('defineCustomElement', () => {
detail: [1],
})
})
// #7293
test('emit in an async component wrapper with properties bound', async () => {
const E = defineCustomElement(
@ -488,6 +492,19 @@ describe('defineCustomElement', () => {
detail: [1],
})
})
test('emit with options', async () => {
container.innerHTML = `<my-el-emits></my-el-emits>`
const e = container.childNodes[0] as VueElement
const spy = vi.fn()
e.addEventListener('my-wheel', spy)
e.shadowRoot!.childNodes[0].dispatchEvent(new CustomEvent('wheel'))
expect(spy).toHaveBeenCalledTimes(1)
expect(spy.mock.calls[0][0]).toMatchObject({
bubbles: true,
detail: [{ bubbles: true }, 1],
})
})
})
describe('slots', () => {

View File

@ -27,7 +27,14 @@ import {
nextTick,
warn,
} from '@vue/runtime-core'
import { camelize, extend, hyphenate, isArray, toNumber } from '@vue/shared'
import {
camelize,
extend,
hyphenate,
isArray,
isPlainObject,
toNumber,
} from '@vue/shared'
import { hydrate, render } from '.'
export type VueElementConstructor<P = {}> = {
@ -405,9 +412,12 @@ export class VueElement extends BaseClass {
const dispatch = (event: string, args: any[]) => {
this.dispatchEvent(
new CustomEvent(event, {
detail: args,
}),
new CustomEvent(
event,
isPlainObject(args[0])
? extend({ detail: args }, args[0])
: { detail: args },
),
)
}