Skip to content

Commit 00ab9e2

Browse files
committed
refactor: adjust event options handling to be JSX friendly
1 parent e3d30ba commit 00ab9e2

File tree

6 files changed

+33
-37
lines changed

6 files changed

+33
-37
lines changed

packages/compiler-dom/__tests__/transforms/vOn.spec.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ describe('compiler-dom: transform v-on', () => {
7777
it('should support multiple modifiers and event options w/ prefixIdentifiers: true', () => {
7878
const {
7979
props: [prop]
80-
} = parseWithVOn(`<div @click.stop.capture.passive="test"/>`, {
80+
} = parseWithVOn(`<div @click.stop.capture.once="test"/>`, {
8181
prefixIdentifiers: true
8282
})
8383
expect(prop).toMatchObject({
8484
type: NodeTypes.JS_PROPERTY,
8585
key: {
86-
content: `onClick.capture.passive`
86+
content: `onClickCaptureOnce`
8787
},
8888
value: {
8989
callee: V_ON_WITH_MODIFIERS,
@@ -101,7 +101,7 @@ describe('compiler-dom: transform v-on', () => {
101101
expect(prop).toMatchObject({
102102
type: NodeTypes.JS_PROPERTY,
103103
key: {
104-
content: `onKeydown.capture`
104+
content: `onKeydownCapture`
105105
},
106106
value: {
107107
callee: V_ON_WITH_KEYS,
@@ -274,7 +274,7 @@ describe('compiler-dom: transform v-on', () => {
274274
)
275275
expect(prop).toMatchObject({
276276
key: {
277-
content: `onKeyup.capture`
277+
content: `onKeyupCapture`
278278
},
279279
value: {
280280
type: NodeTypes.JS_CACHE_EXPRESSION,

packages/compiler-dom/src/transforms/vOn.ts

+6-11
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
isStaticExp
1212
} from '@vue/compiler-core'
1313
import { V_ON_WITH_MODIFIERS, V_ON_WITH_KEYS } from '../runtimeHelpers'
14-
import { makeMap } from '@vue/shared'
14+
import { makeMap, capitalize } from '@vue/shared'
1515

1616
const isEventOptionModifier = /*#__PURE__*/ makeMap(`passive,once,capture`)
1717
const isNonKeyModifier = /*#__PURE__*/ makeMap(
@@ -38,7 +38,8 @@ const resolveModifiers = (key: ExpressionNode, modifiers: string[]) => {
3838
const modifier = modifiers[i]
3939

4040
if (isEventOptionModifier(modifier)) {
41-
// eventOptionModifiers: modifiers for addEventListener() options, e.g. .passive & .capture
41+
// eventOptionModifiers: modifiers for addEventListener() options,
42+
// e.g. .passive & .capture
4243
eventOptionModifiers.push(modifier)
4344
} else {
4445
// runtimeModifiers: modifiers that needs runtime guards
@@ -125,16 +126,10 @@ export const transformOn: DirectiveTransform = (dir, node, context) => {
125126
}
126127

127128
if (eventOptionModifiers.length) {
129+
const modifierPostfix = eventOptionModifiers.map(capitalize).join('')
128130
key = isStaticExp(key)
129-
? createSimpleExpression(
130-
`${key.content}.${eventOptionModifiers.join(`.`)}`,
131-
true
132-
)
133-
: createCompoundExpression([
134-
`(`,
135-
key,
136-
`) + ".${eventOptionModifiers.join(`.`)}"`
137-
])
131+
? createSimpleExpression(`${key.content}${modifierPostfix}`, true)
132+
: createCompoundExpression([`(`, key, `) + "${modifierPostfix}"`])
138133
}
139134

140135
return {

packages/runtime-core/__tests__/componentEmits.spec.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ describe('component: emit', () => {
174174
const fn = jest.fn()
175175
render(
176176
h(Foo, {
177-
'onFoo.once': fn
177+
onFooOnce: fn
178178
}),
179179
nodeOps.createElement('div')
180180
)
@@ -213,8 +213,8 @@ describe('component: emit', () => {
213213

214214
test('.once listeners', () => {
215215
const def2 = { emits: { click: null } }
216-
expect(isEmitListener(def2, 'onClick.once')).toBe(true)
217-
expect(isEmitListener(def2, 'onclick.once')).toBe(false)
216+
expect(isEmitListener(def2, 'onClickOnce')).toBe(true)
217+
expect(isEmitListener(def2, 'onclickOnce')).toBe(false)
218218
})
219219
})
220220
})

packages/runtime-core/src/componentEmits.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export function emit(
7676
handler = props[handlerName]
7777
}
7878
if (!handler) {
79-
handler = props[handlerName + `.once`]
79+
handler = props[handlerName + `Once`]
8080
if (!instance.emitted) {
8181
;(instance.emitted = {} as Record<string, boolean>)[handlerName] = true
8282
} else if (instance.emitted[handlerName]) {
@@ -136,7 +136,7 @@ export function isEmitListener(comp: Component, key: string): boolean {
136136
if (!isOn(key) || !(emits = normalizeEmitsOptions(comp))) {
137137
return false
138138
}
139-
key = key.replace(/\.once$/, '')
139+
key = key.replace(/Once$/, '')
140140
return (
141141
hasOwn(emits, key[2].toLowerCase() + key.slice(3)) ||
142142
hasOwn(emits, key.slice(2))

packages/runtime-dom/__tests__/patchEvents.spec.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ describe(`runtime-dom: events patching`, () => {
6161
const el = document.createElement('div')
6262
const event = new Event('click')
6363
const fn = jest.fn()
64-
patchProp(el, 'onClick.once.capture', null, fn)
64+
patchProp(el, 'onClickOnceCapture', null, fn)
6565
el.dispatchEvent(event)
6666
await timeout()
6767
el.dispatchEvent(event)
@@ -73,13 +73,17 @@ describe(`runtime-dom: events patching`, () => {
7373
const el = document.createElement('div')
7474
const event = new Event('click')
7575
const fn = jest.fn()
76-
patchProp(el, 'onClick.capture', null, fn)
77-
patchProp(el, 'onClick.capture', fn, null)
76+
patchProp(el, 'onClickCapture', null, fn)
7877
el.dispatchEvent(event)
7978
await timeout()
79+
expect(fn).toHaveBeenCalledTimes(1)
80+
81+
patchProp(el, 'onClickCapture', fn, null)
8082
el.dispatchEvent(event)
8183
await timeout()
82-
expect(fn).not.toHaveBeenCalled()
84+
el.dispatchEvent(event)
85+
await timeout()
86+
expect(fn).toHaveBeenCalledTimes(1)
8387
})
8488

8589
it('should support native onclick', async () => {

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

+10-13
Original file line numberDiff line numberDiff line change
@@ -82,23 +82,20 @@ export function patchEvent(
8282
}
8383
}
8484

85-
const optionsModifierRE = /\.(once|passive|capture)\b/g
85+
const optionsModifierRE = /(?:Once|Passive|Capture)$/
8686

8787
function parseName(name: string): [string, EventListenerOptions | undefined] {
88-
name = name.slice(2).toLowerCase()
88+
let options: EventListenerOptions | undefined
8989
if (optionsModifierRE.test(name)) {
90-
const options: EventListenerOptions = {}
91-
name = name.replace(
92-
optionsModifierRE,
93-
(_, key: keyof EventListenerOptions) => {
94-
options[key] = true
95-
return ''
96-
}
97-
)
98-
return [name, options]
99-
} else {
100-
return [name, undefined]
90+
options = {}
91+
let m
92+
while ((m = name.match(optionsModifierRE))) {
93+
name = name.slice(0, name.length - m[0].length)
94+
;(options as any)[m[0].toLowerCase()] = true
95+
options
96+
}
10197
}
98+
return [name.slice(2).toLowerCase(), options]
10299
}
103100

104101
function createInvoker(

0 commit comments

Comments
 (0)