Browse Source

feat: v-on automatic key inference

dev
Evan You 7 years ago
parent
commit
4987eeb3a7
  1. 2
      flow/component.js
  2. 9
      src/compiler/codegen/events.js
  3. 12
      src/core/instance/render-helpers/check-keycodes.js
  4. 12
      test/unit/features/directives/on.spec.js
  5. 14
      test/unit/modules/compiler/codegen.spec.js

2
flow/component.js

@ -126,7 +126,7 @@ declare interface Component {
// apply v-on object // apply v-on object
_g: (data: any, value: any) => VNodeData; _g: (data: any, value: any) => VNodeData;
// check custom keyCode // check custom keyCode
_k: (eventKeyCode: number, key: string, builtInAlias: number | Array<number> | void) => boolean; _k: (eventKeyCode: number, key: string, builtInAlias?: number | Array<number>, eventKeyName?: string) => ?boolean;
// resolve scoped slots // resolve scoped slots
_u: (scopedSlots: ScopedSlotsData, res?: Object) => { [key: string]: Function }; _u: (scopedSlots: ScopedSlotsData, res?: Object) => { [key: string]: Function };

9
src/compiler/codegen/events.js

@ -124,6 +124,11 @@ function genFilterCode (key: string): string {
if (keyVal) { if (keyVal) {
return `$event.keyCode!==${keyVal}` return `$event.keyCode!==${keyVal}`
} }
const alias = keyCodes[key] const code = keyCodes[key]
return `_k($event.keyCode,${JSON.stringify(key)}${alias ? ',' + JSON.stringify(alias) : ''})` return (
`_k($event.keyCode,` +
`${JSON.stringify(key)},` +
`${JSON.stringify(code)},` +
`$event.key)`
)
} }

12
src/core/instance/render-helpers/check-keycodes.js

@ -1,19 +1,27 @@
/* @flow */ /* @flow */
import config from 'core/config' import config from 'core/config'
import { hyphenate } from 'shared/util'
/** /**
* Runtime helper for checking keyCodes from config. * Runtime helper for checking keyCodes from config.
* exposed as Vue.prototype._k
* passing in eventKeyName as last argument separately for backwards compat
*/ */
export function checkKeyCodes ( export function checkKeyCodes (
eventKeyCode: number, eventKeyCode: number,
key: string, key: string,
builtInAlias: number | Array<number> | void builtInAlias?: number | Array<number>,
): boolean { eventKeyName?: string
): ?boolean {
const keyCodes = config.keyCodes[key] || builtInAlias const keyCodes = config.keyCodes[key] || builtInAlias
if (keyCodes) {
if (Array.isArray(keyCodes)) { if (Array.isArray(keyCodes)) {
return keyCodes.indexOf(eventKeyCode) === -1 return keyCodes.indexOf(eventKeyCode) === -1
} else { } else {
return keyCodes !== eventKeyCode return keyCodes !== eventKeyCode
} }
} else if (eventKeyName) {
return hyphenate(eventKeyName) !== key
}
} }

12
test/unit/features/directives/on.spec.js

@ -205,6 +205,18 @@ describe('Directive v-on', () => {
expect(spy).toHaveBeenCalled() expect(spy).toHaveBeenCalled()
}) })
it('should support automatic key name inference', () => {
vm = new Vue({
el,
template: `<input @keyup.arrow-right="foo">`,
methods: { foo: spy }
})
triggerEvent(vm.$el, 'keyup', e => {
e.key = 'ArrowRight'
})
expect(spy).toHaveBeenCalled()
})
// ctrl, shift, alt, meta // ctrl, shift, alt, meta
it('should support system modifers', () => { it('should support system modifers', () => {
vm = new Vue({ vm = new Vue({

14
test/unit/modules/compiler/codegen.spec.js

@ -243,17 +243,17 @@ describe('codegen', () => {
it('generate events with keycode', () => { it('generate events with keycode', () => {
assertCodegen( assertCodegen(
'<input @input.enter="onInput">', '<input @input.enter="onInput">',
`with(this){return _c('input',{on:{"input":function($event){if(!('button' in $event)&&_k($event.keyCode,"enter",13))return null;onInput($event)}}})}` `with(this){return _c('input',{on:{"input":function($event){if(!('button' in $event)&&_k($event.keyCode,"enter",13,$event.key))return null;onInput($event)}}})}`
) )
// multiple keycodes (delete) // multiple keycodes (delete)
assertCodegen( assertCodegen(
'<input @input.delete="onInput">', '<input @input.delete="onInput">',
`with(this){return _c('input',{on:{"input":function($event){if(!('button' in $event)&&_k($event.keyCode,"delete",[8,46]))return null;onInput($event)}}})}` `with(this){return _c('input',{on:{"input":function($event){if(!('button' in $event)&&_k($event.keyCode,"delete",[8,46],$event.key))return null;onInput($event)}}})}`
) )
// multiple keycodes (chained) // multiple keycodes (chained)
assertCodegen( assertCodegen(
'<input @keydown.enter.delete="onInput">', '<input @keydown.enter.delete="onInput">',
`with(this){return _c('input',{on:{"keydown":function($event){if(!('button' in $event)&&_k($event.keyCode,"enter",13)&&_k($event.keyCode,"delete",[8,46]))return null;onInput($event)}}})}` `with(this){return _c('input',{on:{"keydown":function($event){if(!('button' in $event)&&_k($event.keyCode,"enter",13,$event.key)&&_k($event.keyCode,"delete",[8,46],$event.key))return null;onInput($event)}}})}`
) )
// number keycode // number keycode
assertCodegen( assertCodegen(
@ -263,7 +263,7 @@ describe('codegen', () => {
// custom keycode // custom keycode
assertCodegen( assertCodegen(
'<input @input.custom="onInput">', '<input @input.custom="onInput">',
`with(this){return _c('input',{on:{"input":function($event){if(!('button' in $event)&&_k($event.keyCode,"custom"))return null;onInput($event)}}})}` `with(this){return _c('input',{on:{"input":function($event){if(!('button' in $event)&&_k($event.keyCode,"custom",undefined,$event.key))return null;onInput($event)}}})}`
) )
}) })
@ -286,12 +286,12 @@ describe('codegen', () => {
it('generate events with generic modifiers and keycode correct order', () => { it('generate events with generic modifiers and keycode correct order', () => {
assertCodegen( assertCodegen(
'<input @keydown.enter.prevent="onInput">', '<input @keydown.enter.prevent="onInput">',
`with(this){return _c('input',{on:{"keydown":function($event){if(!('button' in $event)&&_k($event.keyCode,"enter",13))return null;$event.preventDefault();onInput($event)}}})}` `with(this){return _c('input',{on:{"keydown":function($event){if(!('button' in $event)&&_k($event.keyCode,"enter",13,$event.key))return null;$event.preventDefault();onInput($event)}}})}`
) )
assertCodegen( assertCodegen(
'<input @keydown.enter.stop="onInput">', '<input @keydown.enter.stop="onInput">',
`with(this){return _c('input',{on:{"keydown":function($event){if(!('button' in $event)&&_k($event.keyCode,"enter",13))return null;$event.stopPropagation();onInput($event)}}})}` `with(this){return _c('input',{on:{"keydown":function($event){if(!('button' in $event)&&_k($event.keyCode,"enter",13,$event.key))return null;$event.stopPropagation();onInput($event)}}})}`
) )
}) })
@ -398,7 +398,7 @@ describe('codegen', () => {
// with modifiers // with modifiers
assertCodegen( assertCodegen(
`<input @keyup.enter="e=>current++">`, `<input @keyup.enter="e=>current++">`,
`with(this){return _c('input',{on:{"keyup":function($event){if(!('button' in $event)&&_k($event.keyCode,"enter",13))return null;(e=>current++)($event)}}})}` `with(this){return _c('input',{on:{"keyup":function($event){if(!('button' in $event)&&_k($event.keyCode,"enter",13,$event.key))return null;(e=>current++)($event)}}})}`
) )
}) })

Loading…
Cancel
Save