]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(custom-element): support emit with options
authorEvan You <evan@vuejs.org>
Sat, 3 Aug 2024 05:46:58 +0000 (13:46 +0800)
committerEvan You <evan@vuejs.org>
Sat, 3 Aug 2024 05:46:58 +0000 (13:46 +0800)
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

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

index ab4d6f479390a61bc2caa7db36303b1023f2c356..1ed7cc25311de275d01ca084b3d06ef8ce83af36 100644 (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', () => {
index 5c421b38ed58029e084b1f800d0aeb99f22611bf..476723707912c3e8afa66544764ac19efba3fdf6 100644 (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 },
+            ),
           )
         }