diff --git a/packages/compiler-core/src/transforms/vOn.ts b/packages/compiler-core/src/transforms/vOn.ts index 113a1181880..487db39232b 100644 --- a/packages/compiler-core/src/transforms/vOn.ts +++ b/packages/compiler-core/src/transforms/vOn.ts @@ -56,6 +56,9 @@ export const transformOn: DirectiveTransform = ( // handler processing let exp: ExpressionNode | undefined = dir.exp + if (exp && !exp.content.trim()) { + exp = undefined + } let isCacheable: boolean = !exp if (exp) { const isMemberExp = isMemberExpression(exp.content) diff --git a/packages/compiler-dom/__tests__/transforms/vOn.spec.ts b/packages/compiler-dom/__tests__/transforms/vOn.spec.ts index 7d56b3a8343..adc063da2f5 100644 --- a/packages/compiler-dom/__tests__/transforms/vOn.spec.ts +++ b/packages/compiler-dom/__tests__/transforms/vOn.spec.ts @@ -152,6 +152,58 @@ describe('compiler-dom: transform v-on', () => { }) }) + test('should transform click.right', () => { + const { + props: [prop] + } = parseWithVOn(`
`) + expect(prop.key).toMatchObject({ + type: NodeTypes.SIMPLE_EXPRESSION, + content: `onContextmenu` + }) + + // dynamic + const { + props: [prop2] + } = parseWithVOn(``) + // ("on" + (event)).toLowerCase() === "onclick" ? "onContextmenu" : ("on" + (event)) + expect(prop2.key).toMatchObject({ + type: NodeTypes.COMPOUND_EXPRESSION, + children: [ + `(`, + { children: [`"on" + (`, { content: 'event' }, `)`] }, + `).toLowerCase() === "onclick" ? "onContextmenu" : (`, + { children: [`"on" + (`, { content: 'event' }, `)`] }, + `)` + ] + }) + }) + + test('should transform click.middle', () => { + const { + props: [prop] + } = parseWithVOn(``) + expect(prop.key).toMatchObject({ + type: NodeTypes.SIMPLE_EXPRESSION, + content: `onMouseup` + }) + + // dynamic + const { + props: [prop2] + } = parseWithVOn(``) + // ("on" + (event)).toLowerCase() === "onclick" ? "onMouseup" : ("on" + (event)) + expect(prop2.key).toMatchObject({ + type: NodeTypes.COMPOUND_EXPRESSION, + children: [ + `(`, + { children: [`"on" + (`, { content: 'event' }, `)`] }, + `).toLowerCase() === "onclick" ? "onMouseup" : (`, + { children: [`"on" + (`, { content: 'event' }, `)`] }, + `)` + ] + }) + }) + test('cache handler w/ modifiers', () => { const { root, diff --git a/packages/compiler-dom/src/transforms/vOn.ts b/packages/compiler-dom/src/transforms/vOn.ts index dd6696b824a..b4c013d43ff 100644 --- a/packages/compiler-dom/src/transforms/vOn.ts +++ b/packages/compiler-dom/src/transforms/vOn.ts @@ -5,7 +5,9 @@ import { createCallExpression, createObjectExpression, createSimpleExpression, - NodeTypes + NodeTypes, + createCompoundExpression, + ExpressionNode } from '@vue/compiler-core' import { V_ON_WITH_MODIFIERS, V_ON_WITH_KEYS } from '../runtimeHelpers' import { makeMap } from '@vue/shared' @@ -52,6 +54,24 @@ const generateModifiers = (modifiers: string[]) => { } } +const transformClick = (key: ExpressionNode, event: string) => { + const isStaticClick = + key.type === NodeTypes.SIMPLE_EXPRESSION && + key.isStatic && + key.content.toLowerCase() === 'onclick' + return isStaticClick + ? createSimpleExpression(event, true) + : key.type !== NodeTypes.SIMPLE_EXPRESSION + ? createCompoundExpression([ + `(`, + key, + `).toLowerCase() === "onclick" ? "${event}" : (`, + key, + `)` + ]) + : key +} + export const transformOn: DirectiveTransform = (dir, node, context) => { return baseTransform(dir, node, context, baseResult => { const { modifiers } = dir @@ -64,6 +84,14 @@ export const transformOn: DirectiveTransform = (dir, node, context) => { eventOptionModifiers } = generateModifiers(modifiers) + // normalize click.right and click.middle since they don't actually fire + if (nonKeyModifiers.includes('right')) { + key = transformClick(key, `onContextmenu`) + } + if (nonKeyModifiers.includes('middle')) { + key = transformClick(key, `onMouseup`) + } + if (nonKeyModifiers.length) { handlerExp = createCallExpression(context.helper(V_ON_WITH_MODIFIERS), [ handlerExp,