diff --git a/flow/component.js b/flow/component.js index 381943edaf7..71867ba3c71 100644 --- a/flow/component.js +++ b/flow/component.js @@ -126,7 +126,7 @@ declare interface Component { // apply v-on object _g: (data: any, value: any) => VNodeData; // check custom keyCode - _k: (eventKeyCode: number, key: string, builtInAlias: number | Array | void) => boolean; + _k: (eventKeyCode: number, key: string, builtInAlias?: number | Array, eventKeyName?: string) => ?boolean; // resolve scoped slots _u: (scopedSlots: ScopedSlotsData, res?: Object) => { [key: string]: Function }; diff --git a/src/compiler/codegen/events.js b/src/compiler/codegen/events.js index 67ae0368b65..b15d93160d3 100644 --- a/src/compiler/codegen/events.js +++ b/src/compiler/codegen/events.js @@ -124,6 +124,11 @@ function genFilterCode (key: string): string { if (keyVal) { return `$event.keyCode!==${keyVal}` } - const alias = keyCodes[key] - return `_k($event.keyCode,${JSON.stringify(key)}${alias ? ',' + JSON.stringify(alias) : ''})` + const code = keyCodes[key] + return ( + `_k($event.keyCode,` + + `${JSON.stringify(key)},` + + `${JSON.stringify(code)},` + + `$event.key)` + ) } diff --git a/src/core/instance/render-helpers/check-keycodes.js b/src/core/instance/render-helpers/check-keycodes.js index 7d878009d10..8e77f29b9e4 100644 --- a/src/core/instance/render-helpers/check-keycodes.js +++ b/src/core/instance/render-helpers/check-keycodes.js @@ -1,19 +1,27 @@ /* @flow */ import config from 'core/config' +import { hyphenate } from 'shared/util' /** * 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 ( eventKeyCode: number, key: string, - builtInAlias: number | Array | void -): boolean { + builtInAlias?: number | Array, + eventKeyName?: string +): ?boolean { const keyCodes = config.keyCodes[key] || builtInAlias - if (Array.isArray(keyCodes)) { - return keyCodes.indexOf(eventKeyCode) === -1 - } else { - return keyCodes !== eventKeyCode + if (keyCodes) { + if (Array.isArray(keyCodes)) { + return keyCodes.indexOf(eventKeyCode) === -1 + } else { + return keyCodes !== eventKeyCode + } + } else if (eventKeyName) { + return hyphenate(eventKeyName) !== key } } diff --git a/test/unit/features/directives/on.spec.js b/test/unit/features/directives/on.spec.js index 5dd0f1ce409..b65ec37948e 100644 --- a/test/unit/features/directives/on.spec.js +++ b/test/unit/features/directives/on.spec.js @@ -205,6 +205,18 @@ describe('Directive v-on', () => { expect(spy).toHaveBeenCalled() }) + it('should support automatic key name inference', () => { + vm = new Vue({ + el, + template: ``, + methods: { foo: spy } + }) + triggerEvent(vm.$el, 'keyup', e => { + e.key = 'ArrowRight' + }) + expect(spy).toHaveBeenCalled() + }) + // ctrl, shift, alt, meta it('should support system modifers', () => { vm = new Vue({ diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js index 4eb804c3d36..6eaa3d18663 100644 --- a/test/unit/modules/compiler/codegen.spec.js +++ b/test/unit/modules/compiler/codegen.spec.js @@ -243,17 +243,17 @@ describe('codegen', () => { it('generate events with keycode', () => { assertCodegen( '', - `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) assertCodegen( '', - `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) assertCodegen( '', - `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 assertCodegen( @@ -263,7 +263,7 @@ describe('codegen', () => { // custom keycode assertCodegen( '', - `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', () => { assertCodegen( '', - `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( '', - `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 assertCodegen( ``, - `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)}}})}` ) })