Skip to content

Commit 2302dea

Browse files
committed
fix(runtime-dom): support native onxxx handlers
close #927
1 parent cb504c2 commit 2302dea

File tree

3 files changed

+43
-20
lines changed

3 files changed

+43
-20
lines changed

packages/runtime-dom/__tests__/modules/events.spec.ts

+29-11
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ describe(`events`, () => {
77
const el = document.createElement('div')
88
const event = new Event('click')
99
const fn = jest.fn()
10-
patchEvent(el, 'click', null, fn, null)
10+
patchEvent(el, 'onClick', null, fn, null)
1111
el.dispatchEvent(event)
1212
await timeout()
1313
el.dispatchEvent(event)
@@ -22,9 +22,9 @@ describe(`events`, () => {
2222
const event = new Event('click')
2323
const prevFn = jest.fn()
2424
const nextFn = jest.fn()
25-
patchEvent(el, 'click', null, prevFn, null)
25+
patchEvent(el, 'onClick', null, prevFn, null)
2626
el.dispatchEvent(event)
27-
patchEvent(el, 'click', prevFn, nextFn, null)
27+
patchEvent(el, 'onClick', prevFn, nextFn, null)
2828
await timeout()
2929
el.dispatchEvent(event)
3030
await timeout()
@@ -39,7 +39,7 @@ describe(`events`, () => {
3939
const event = new Event('click')
4040
const fn1 = jest.fn()
4141
const fn2 = jest.fn()
42-
patchEvent(el, 'click', null, [fn1, fn2], null)
42+
patchEvent(el, 'onClick', null, [fn1, fn2], null)
4343
el.dispatchEvent(event)
4444
await timeout()
4545
expect(fn1).toHaveBeenCalledTimes(1)
@@ -50,8 +50,8 @@ describe(`events`, () => {
5050
const el = document.createElement('div')
5151
const event = new Event('click')
5252
const fn = jest.fn()
53-
patchEvent(el, 'click', null, fn, null)
54-
patchEvent(el, 'click', fn, null, null)
53+
patchEvent(el, 'onClick', null, fn, null)
54+
patchEvent(el, 'onClick', fn, null, null)
5555
el.dispatchEvent(event)
5656
await timeout()
5757
expect(fn).not.toHaveBeenCalled()
@@ -67,7 +67,7 @@ describe(`events`, () => {
6767
once: true
6868
}
6969
}
70-
patchEvent(el, 'click', null, nextValue, null)
70+
patchEvent(el, 'onClick', null, nextValue, null)
7171
el.dispatchEvent(event)
7272
await timeout()
7373
el.dispatchEvent(event)
@@ -86,8 +86,8 @@ describe(`events`, () => {
8686
once: true
8787
}
8888
}
89-
patchEvent(el, 'click', null, prevFn, null)
90-
patchEvent(el, 'click', prevFn, nextValue, null)
89+
patchEvent(el, 'onClick', null, prevFn, null)
90+
patchEvent(el, 'onClick', prevFn, nextValue, null)
9191
el.dispatchEvent(event)
9292
await timeout()
9393
el.dispatchEvent(event)
@@ -106,12 +106,30 @@ describe(`events`, () => {
106106
once: true
107107
}
108108
}
109-
patchEvent(el, 'click', null, nextValue, null)
110-
patchEvent(el, 'click', nextValue, null, null)
109+
patchEvent(el, 'onClick', null, nextValue, null)
110+
patchEvent(el, 'onClick', nextValue, null, null)
111111
el.dispatchEvent(event)
112112
await timeout()
113113
el.dispatchEvent(event)
114114
await timeout()
115115
expect(fn).not.toHaveBeenCalled()
116116
})
117+
118+
it('should assign native onclick attribute', async () => {
119+
const el = document.createElement('div')
120+
const event = new Event('click')
121+
const fn = ((window as any)._nativeClickSpy = jest.fn())
122+
123+
patchEvent(el, 'onclick', null, '_nativeClickSpy()' as any)
124+
el.dispatchEvent(event)
125+
await timeout()
126+
expect(fn).toHaveBeenCalledTimes(1)
127+
128+
const fn2 = jest.fn()
129+
patchEvent(el, 'onclick', null, fn2)
130+
el.dispatchEvent(event)
131+
await timeout()
132+
expect(fn).toHaveBeenCalledTimes(1)
133+
expect(fn2).toHaveBeenCalledTimes(1)
134+
})
117135
})

packages/runtime-dom/src/modules/events.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { EMPTY_OBJ } from '@vue/shared'
1+
import { EMPTY_OBJ, isString } from '@vue/shared'
22
import {
33
ComponentInternalInstance,
44
callWithAsyncErrorHandling
@@ -66,11 +66,22 @@ export function removeEventListener(
6666

6767
export function patchEvent(
6868
el: Element,
69-
name: string,
69+
rawName: string,
7070
prevValue: EventValueWithOptions | EventValue | null,
7171
nextValue: EventValueWithOptions | EventValue | null,
7272
instance: ComponentInternalInstance | null = null
7373
) {
74+
// support native onxxx handlers
75+
if (rawName in el) {
76+
if (isString(nextValue)) {
77+
el.setAttribute(rawName, nextValue)
78+
} else {
79+
;(el as any)[rawName] = nextValue
80+
}
81+
return
82+
}
83+
84+
const name = rawName.slice(2).toLowerCase()
7485
const prevOptions = prevValue && 'options' in prevValue && prevValue.options
7586
const nextOptions = nextValue && 'options' in nextValue && nextValue.options
7687
const invoker = prevValue && prevValue.invoker

packages/runtime-dom/src/patchProp.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,7 @@ export const patchProp: RendererOptions<Node, Element>['patchProp'] = (
2929
if (isOn(key)) {
3030
// ignore v-model listeners
3131
if (key.indexOf('onUpdate:') < 0) {
32-
patchEvent(
33-
el,
34-
key.slice(2).toLowerCase(),
35-
prevValue,
36-
nextValue,
37-
parentComponent
38-
)
32+
patchEvent(el, key, prevValue, nextValue, parentComponent)
3933
}
4034
} else if (!isSVG && key in el) {
4135
patchDOMProp(

0 commit comments

Comments
 (0)