Skip to content

Commit

Permalink
fix(custom-elements): also dispatch hyphenated version of emitted eve…
Browse files Browse the repository at this point in the history
…nts (vuejs#5378)

fix vuejs#5373
  • Loading branch information
LinusBorg authored and zhangzhonghe committed Apr 12, 2023
1 parent 6eff5a8 commit ab56759
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 4 deletions.
24 changes: 22 additions & 2 deletions packages/runtime-dom/__tests__/customElement.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,12 @@ describe('defineCustomElement', () => {
emit('created')
return () =>
h('div', {
onClick: () => emit('my-click', 1)
onClick: () => {
emit('my-click', 1)
},
onMousedown: () => {
emit('myEvent', 1) // validate hypenization
}
})
}
})
Expand All @@ -252,11 +257,26 @@ describe('defineCustomElement', () => {
const spy = jest.fn()
e.addEventListener('my-click', spy)
e.shadowRoot!.childNodes[0].dispatchEvent(new CustomEvent('click'))
expect(spy).toHaveBeenCalled()
expect(spy).toHaveBeenCalledTimes(1)
expect(spy.mock.calls[0][0]).toMatchObject({
detail: [1]
})
})

// #5373
test('case transform for camelCase event', () => {
container.innerHTML = `<my-el-emits></my-el-emits>`
const e = container.childNodes[0] as VueElement
const spy1 = jest.fn()
e.addEventListener('myEvent', spy1)
const spy2 = jest.fn()
// emitting myEvent, but listening for my-event. This happens when
// using the custom element in a Vue template
e.addEventListener('my-event', spy2)
e.shadowRoot!.childNodes[0].dispatchEvent(new CustomEvent('mousedown'))
expect(spy1).toHaveBeenCalledTimes(1)
expect(spy2).toHaveBeenCalledTimes(1)
})
})

describe('slots', () => {
Expand Down
13 changes: 11 additions & 2 deletions packages/runtime-dom/src/apiCustomElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,15 +351,24 @@ export class VueElement extends BaseClass {
}
}

// intercept emit
instance.emit = (event: string, ...args: any[]) => {
const dispatch = (event: string, args: any[]) => {
this.dispatchEvent(
new CustomEvent(event, {
detail: args
})
)
}

// intercept emit
instance.emit = (event: string, ...args: any[]) => {
// dispatch both the raw and hyphenated versions of an event
// to match Vue behavior
dispatch(event, args)
if (hyphenate(event) !== event) {
dispatch(hyphenate(event), args)
}
}

// locate nearest Vue custom element parent for provide/inject
let parent: Node | null = this
while (
Expand Down

0 comments on commit ab56759

Please sign in to comment.