Skip to content

Commit

Permalink
feat(custom-element): support emit with options
Browse files Browse the repository at this point in the history
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
  • Loading branch information
yyx990803 committed Aug 3, 2024
1 parent 7f2c505 commit e181bff
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 4 deletions.
17 changes: 17 additions & 0 deletions packages/runtime-dom/__tests__/customElement.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,9 @@ describe('defineCustomElement', () => {
onMousedown: () => {
emit('myEvent', 1) // validate hyphenation
},
onWheel: () => {
emit('my-wheel', { bubbles: true }, 1)
},
})
},
})
Expand Down Expand Up @@ -467,6 +470,7 @@ describe('defineCustomElement', () => {
detail: [1],
})
})

// #7293
test('emit in an async component wrapper with properties bound', async () => {
const E = defineCustomElement(
Expand All @@ -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', () => {
Expand Down
18 changes: 14 additions & 4 deletions packages/runtime-dom/src/apiCustomElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}> = {
Expand Down Expand Up @@ -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 },
),
)
}

Expand Down

0 comments on commit e181bff

Please # to comment.