diff --git a/flow/component.js b/flow/component.js index e8e1ebee762..f18406da6f6 100644 --- a/flow/component.js +++ b/flow/component.js @@ -104,8 +104,8 @@ declare interface Component { _t: (name: string, fallback: ?Array, props: ?Object) => ?Array; // apply v-bind object _b: (data: any, value: any, asProp?: boolean) => VNodeData; - // retrive custom keyCode - _k: (key: string) => ?number; + // check custom keyCode + _k: (eventKeyCode: number, key: string, buildinAlias: number | Array | void) => boolean; // allow dynamic method registration [key: string]: any diff --git a/src/compiler/codegen/events.js b/src/compiler/codegen/events.js index 51079047d31..44308ffcc10 100644 --- a/src/compiler/codegen/events.js +++ b/src/compiler/codegen/events.js @@ -74,20 +74,15 @@ function genHandler ( } function genKeyFilter (keys: Array): string { - const code = keys.length === 1 - ? normalizeKeyCode(keys[0]) - : Array.prototype.concat.apply([], keys.map(normalizeKeyCode)) - if (Array.isArray(code)) { - return `if(${code.map(c => `$event.keyCode!==${c}`).join('&&')})return;` - } else { - return `if($event.keyCode!==${code})return;` - } + const code = keys.map(genFilterCode) + return `if(${code.join('&&')})return;` } -function normalizeKeyCode (key) { - return ( - parseInt(key, 10) || // number keyCode - keyCodes[key] || // built-in alias - `_k(${JSON.stringify(key)})` // custom alias - ) +function genFilterCode (key: number | string): string { + const keyVal = parseInt(key, 10) + if (keyVal) { + return `$event.keyCode!==${keyVal}` + } + const alias = keyCodes[key] + return `_k($event.keyCode,${JSON.stringify(key)}${alias ? ',' + JSON.stringify(alias) : ''})` } diff --git a/src/core/instance/render.js b/src/core/instance/render.js index 5bc48587e09..a4a0f7afedb 100644 --- a/src/core/instance/render.js +++ b/src/core/instance/render.js @@ -238,9 +238,18 @@ export function renderMixin (Vue: Class) { return data } - // expose v-on keyCodes - Vue.prototype._k = function getKeyCodes (key: string): any { - return config.keyCodes[key] + // check v-on keyCodes + Vue.prototype._k = function checkKeyCodes ( + eventKeyCode: number, + key: string, + buildinAlias: number | Array | void + ): boolean { + const keyCodes = config.keyCodes[key] || buildinAlias + if (Array.isArray(keyCodes)) { + return keyCodes.indexOf(eventKeyCode) === -1 + } else { + return keyCodes !== eventKeyCode + } } } diff --git a/test/unit/features/directives/on.spec.js b/test/unit/features/directives/on.spec.js index 3475df77310..5cfcd8e1a29 100644 --- a/test/unit/features/directives/on.spec.js +++ b/test/unit/features/directives/on.spec.js @@ -152,6 +152,28 @@ describe('Directive v-on', () => { expect(spy).toHaveBeenCalled() }) + it('should override build-in keyCode', () => { + Vue.config.keyCodes.up = [1, 87] + vm = new Vue({ + el, + template: ``, + methods: { foo: spy } + }) + triggerEvent(vm.$el, 'keyup', e => { + e.keyCode = 87 + }) + expect(spy).toHaveBeenCalled() + triggerEvent(vm.$el, 'keyup', e => { + e.keyCode = 1 + }) + expect(spy).toHaveBeenCalledTimes(2) + // should not affect build-in down keycode + triggerEvent(vm.$el, 'keyup', e => { + e.keyCode = 40 + }) + expect(spy).toHaveBeenCalledTimes(3) + }) + it('should bind to a child component', () => { Vue.component('bar', { template: 'Hello' diff --git a/test/unit/modules/compiler/codegen.spec.js b/test/unit/modules/compiler/codegen.spec.js index 9700d3ce97c..8750f404acc 100644 --- a/test/unit/modules/compiler/codegen.spec.js +++ b/test/unit/modules/compiler/codegen.spec.js @@ -224,17 +224,17 @@ describe('codegen', () => { it('generate events with keycode', () => { assertCodegen( '', - `with(this){return _h('input',{on:{"input":function($event){if($event.keyCode!==13)return;onInput($event)}}})}` + `with(this){return _h('input',{on:{"input":function($event){if(_k($event.keyCode,"enter",13))return;onInput($event)}}})}` ) // multiple keycodes (delete) assertCodegen( '', - `with(this){return _h('input',{on:{"input":function($event){if($event.keyCode!==8&&$event.keyCode!==46)return;onInput($event)}}})}` + `with(this){return _h('input',{on:{"input":function($event){if(_k($event.keyCode,"delete",[8,46]))return;onInput($event)}}})}` ) // multiple keycodes (chained) assertCodegen( '', - `with(this){return _h('input',{on:{"keydown":function($event){if($event.keyCode!==13&&$event.keyCode!==8&&$event.keyCode!==46)return;onInput($event)}}})}` + `with(this){return _h('input',{on:{"keydown":function($event){if(_k($event.keyCode,"enter",13)&&_k($event.keyCode,"delete",[8,46]))return;onInput($event)}}})}` ) // number keycode assertCodegen( @@ -244,7 +244,7 @@ describe('codegen', () => { // custom keycode assertCodegen( '', - `with(this){return _h('input',{on:{"input":function($event){if($event.keyCode!==_k("custom"))return;onInput($event)}}})}` + `with(this){return _h('input',{on:{"input":function($event){if(_k($event.keyCode,"custom"))return;onInput($event)}}})}` ) })