refactor: adjust event options handling to be JSX friendly
This commit is contained in:
parent
e3d30ba26f
commit
00ab9e2e85
@ -77,13 +77,13 @@ describe('compiler-dom: transform v-on', () => {
|
|||||||
it('should support multiple modifiers and event options w/ prefixIdentifiers: true', () => {
|
it('should support multiple modifiers and event options w/ prefixIdentifiers: true', () => {
|
||||||
const {
|
const {
|
||||||
props: [prop]
|
props: [prop]
|
||||||
} = parseWithVOn(`<div @click.stop.capture.passive="test"/>`, {
|
} = parseWithVOn(`<div @click.stop.capture.once="test"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true
|
||||||
})
|
})
|
||||||
expect(prop).toMatchObject({
|
expect(prop).toMatchObject({
|
||||||
type: NodeTypes.JS_PROPERTY,
|
type: NodeTypes.JS_PROPERTY,
|
||||||
key: {
|
key: {
|
||||||
content: `onClick.capture.passive`
|
content: `onClickCaptureOnce`
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
callee: V_ON_WITH_MODIFIERS,
|
callee: V_ON_WITH_MODIFIERS,
|
||||||
@ -101,7 +101,7 @@ describe('compiler-dom: transform v-on', () => {
|
|||||||
expect(prop).toMatchObject({
|
expect(prop).toMatchObject({
|
||||||
type: NodeTypes.JS_PROPERTY,
|
type: NodeTypes.JS_PROPERTY,
|
||||||
key: {
|
key: {
|
||||||
content: `onKeydown.capture`
|
content: `onKeydownCapture`
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
callee: V_ON_WITH_KEYS,
|
callee: V_ON_WITH_KEYS,
|
||||||
@ -274,7 +274,7 @@ describe('compiler-dom: transform v-on', () => {
|
|||||||
)
|
)
|
||||||
expect(prop).toMatchObject({
|
expect(prop).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `onKeyup.capture`
|
content: `onKeyupCapture`
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
isStaticExp
|
isStaticExp
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { V_ON_WITH_MODIFIERS, V_ON_WITH_KEYS } from '../runtimeHelpers'
|
import { V_ON_WITH_MODIFIERS, V_ON_WITH_KEYS } from '../runtimeHelpers'
|
||||||
import { makeMap } from '@vue/shared'
|
import { makeMap, capitalize } from '@vue/shared'
|
||||||
|
|
||||||
const isEventOptionModifier = /*#__PURE__*/ makeMap(`passive,once,capture`)
|
const isEventOptionModifier = /*#__PURE__*/ makeMap(`passive,once,capture`)
|
||||||
const isNonKeyModifier = /*#__PURE__*/ makeMap(
|
const isNonKeyModifier = /*#__PURE__*/ makeMap(
|
||||||
@ -38,7 +38,8 @@ const resolveModifiers = (key: ExpressionNode, modifiers: string[]) => {
|
|||||||
const modifier = modifiers[i]
|
const modifier = modifiers[i]
|
||||||
|
|
||||||
if (isEventOptionModifier(modifier)) {
|
if (isEventOptionModifier(modifier)) {
|
||||||
// eventOptionModifiers: modifiers for addEventListener() options, e.g. .passive & .capture
|
// eventOptionModifiers: modifiers for addEventListener() options,
|
||||||
|
// e.g. .passive & .capture
|
||||||
eventOptionModifiers.push(modifier)
|
eventOptionModifiers.push(modifier)
|
||||||
} else {
|
} else {
|
||||||
// runtimeModifiers: modifiers that needs runtime guards
|
// runtimeModifiers: modifiers that needs runtime guards
|
||||||
@ -125,16 +126,10 @@ export const transformOn: DirectiveTransform = (dir, node, context) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (eventOptionModifiers.length) {
|
if (eventOptionModifiers.length) {
|
||||||
|
const modifierPostfix = eventOptionModifiers.map(capitalize).join('')
|
||||||
key = isStaticExp(key)
|
key = isStaticExp(key)
|
||||||
? createSimpleExpression(
|
? createSimpleExpression(`${key.content}${modifierPostfix}`, true)
|
||||||
`${key.content}.${eventOptionModifiers.join(`.`)}`,
|
: createCompoundExpression([`(`, key, `) + "${modifierPostfix}"`])
|
||||||
true
|
|
||||||
)
|
|
||||||
: createCompoundExpression([
|
|
||||||
`(`,
|
|
||||||
key,
|
|
||||||
`) + ".${eventOptionModifiers.join(`.`)}"`
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -174,7 +174,7 @@ describe('component: emit', () => {
|
|||||||
const fn = jest.fn()
|
const fn = jest.fn()
|
||||||
render(
|
render(
|
||||||
h(Foo, {
|
h(Foo, {
|
||||||
'onFoo.once': fn
|
onFooOnce: fn
|
||||||
}),
|
}),
|
||||||
nodeOps.createElement('div')
|
nodeOps.createElement('div')
|
||||||
)
|
)
|
||||||
@ -213,8 +213,8 @@ describe('component: emit', () => {
|
|||||||
|
|
||||||
test('.once listeners', () => {
|
test('.once listeners', () => {
|
||||||
const def2 = { emits: { click: null } }
|
const def2 = { emits: { click: null } }
|
||||||
expect(isEmitListener(def2, 'onClick.once')).toBe(true)
|
expect(isEmitListener(def2, 'onClickOnce')).toBe(true)
|
||||||
expect(isEmitListener(def2, 'onclick.once')).toBe(false)
|
expect(isEmitListener(def2, 'onclickOnce')).toBe(false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -76,7 +76,7 @@ export function emit(
|
|||||||
handler = props[handlerName]
|
handler = props[handlerName]
|
||||||
}
|
}
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
handler = props[handlerName + `.once`]
|
handler = props[handlerName + `Once`]
|
||||||
if (!instance.emitted) {
|
if (!instance.emitted) {
|
||||||
;(instance.emitted = {} as Record<string, boolean>)[handlerName] = true
|
;(instance.emitted = {} as Record<string, boolean>)[handlerName] = true
|
||||||
} else if (instance.emitted[handlerName]) {
|
} else if (instance.emitted[handlerName]) {
|
||||||
@ -136,7 +136,7 @@ export function isEmitListener(comp: Component, key: string): boolean {
|
|||||||
if (!isOn(key) || !(emits = normalizeEmitsOptions(comp))) {
|
if (!isOn(key) || !(emits = normalizeEmitsOptions(comp))) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
key = key.replace(/\.once$/, '')
|
key = key.replace(/Once$/, '')
|
||||||
return (
|
return (
|
||||||
hasOwn(emits, key[2].toLowerCase() + key.slice(3)) ||
|
hasOwn(emits, key[2].toLowerCase() + key.slice(3)) ||
|
||||||
hasOwn(emits, key.slice(2))
|
hasOwn(emits, key.slice(2))
|
||||||
|
@ -61,7 +61,7 @@ describe(`runtime-dom: events patching`, () => {
|
|||||||
const el = document.createElement('div')
|
const el = document.createElement('div')
|
||||||
const event = new Event('click')
|
const event = new Event('click')
|
||||||
const fn = jest.fn()
|
const fn = jest.fn()
|
||||||
patchProp(el, 'onClick.once.capture', null, fn)
|
patchProp(el, 'onClickOnceCapture', null, fn)
|
||||||
el.dispatchEvent(event)
|
el.dispatchEvent(event)
|
||||||
await timeout()
|
await timeout()
|
||||||
el.dispatchEvent(event)
|
el.dispatchEvent(event)
|
||||||
@ -73,13 +73,17 @@ describe(`runtime-dom: events patching`, () => {
|
|||||||
const el = document.createElement('div')
|
const el = document.createElement('div')
|
||||||
const event = new Event('click')
|
const event = new Event('click')
|
||||||
const fn = jest.fn()
|
const fn = jest.fn()
|
||||||
patchProp(el, 'onClick.capture', null, fn)
|
patchProp(el, 'onClickCapture', null, fn)
|
||||||
patchProp(el, 'onClick.capture', fn, null)
|
el.dispatchEvent(event)
|
||||||
|
await timeout()
|
||||||
|
expect(fn).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
patchProp(el, 'onClickCapture', fn, null)
|
||||||
el.dispatchEvent(event)
|
el.dispatchEvent(event)
|
||||||
await timeout()
|
await timeout()
|
||||||
el.dispatchEvent(event)
|
el.dispatchEvent(event)
|
||||||
await timeout()
|
await timeout()
|
||||||
expect(fn).not.toHaveBeenCalled()
|
expect(fn).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support native onclick', async () => {
|
it('should support native onclick', async () => {
|
||||||
|
@ -82,23 +82,20 @@ export function patchEvent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const optionsModifierRE = /\.(once|passive|capture)\b/g
|
const optionsModifierRE = /(?:Once|Passive|Capture)$/
|
||||||
|
|
||||||
function parseName(name: string): [string, EventListenerOptions | undefined] {
|
function parseName(name: string): [string, EventListenerOptions | undefined] {
|
||||||
name = name.slice(2).toLowerCase()
|
let options: EventListenerOptions | undefined
|
||||||
if (optionsModifierRE.test(name)) {
|
if (optionsModifierRE.test(name)) {
|
||||||
const options: EventListenerOptions = {}
|
options = {}
|
||||||
name = name.replace(
|
let m
|
||||||
optionsModifierRE,
|
while ((m = name.match(optionsModifierRE))) {
|
||||||
(_, key: keyof EventListenerOptions) => {
|
name = name.slice(0, name.length - m[0].length)
|
||||||
options[key] = true
|
;(options as any)[m[0].toLowerCase()] = true
|
||||||
return ''
|
options
|
||||||
}
|
}
|
||||||
)
|
|
||||||
return [name, options]
|
|
||||||
} else {
|
|
||||||
return [name, undefined]
|
|
||||||
}
|
}
|
||||||
|
return [name.slice(2).toLowerCase(), options]
|
||||||
}
|
}
|
||||||
|
|
||||||
function createInvoker(
|
function createInvoker(
|
||||||
|
Loading…
Reference in New Issue
Block a user