From 362f41181fe7762717a2afef0ba7abb965896715 Mon Sep 17 00:00:00 2001 From: defcc Date: Mon, 28 Nov 2016 00:29:49 +0800 Subject: [PATCH 1/6] support mutliple keys for keycode --- src/compiler/codegen/events.js | 23 +++++++++-------------- src/core/instance/render.js | 13 +++++++++++-- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/compiler/codegen/events.js b/src/compiler/codegen/events.js index 51079047d31..13320ab7b97 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..915b1696f3e 100644 --- a/src/core/instance/render.js +++ b/src/core/instance/render.js @@ -239,8 +239,17 @@ export function renderMixin (Vue: Class) { } // expose v-on keyCodes - Vue.prototype._k = function getKeyCodes (key: string): any { - return config.keyCodes[key] + Vue.prototype._k = function getKeyCodes ( + eventKeyCode: number, + key: string, + buildinAlias: number | Array | void + ): any { + const keyCodes = config.keyCodes[key] || buildinAlias + if (Array.isArray(keyCodes)) { + return keyCodes.indexOf(eventKeyCode) === -1 + } else { + return keyCodes !== eventKeyCode + } } } From fd17eedbe20d3c4124c7447e384829919f7870d0 Mon Sep 17 00:00:00 2001 From: defcc Date: Mon, 28 Nov 2016 00:56:25 +0800 Subject: [PATCH 2/6] update flow type --- flow/component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flow/component.js b/flow/component.js index e8e1ebee762..74ce164ed16 100644 --- a/flow/component.js +++ b/flow/component.js @@ -105,7 +105,7 @@ declare interface Component { // apply v-bind object _b: (data: any, value: any, asProp?: boolean) => VNodeData; // retrive custom keyCode - _k: (key: string) => ?number; + _k: (eventKeyCode: number, key: string, buildinAlias: number | Array | void) => boolean; // allow dynamic method registration [key: string]: any From 54400d0e6f03011c3c1fcae1bf38a10ca5b7e5a6 Mon Sep 17 00:00:00 2001 From: defcc Date: Mon, 28 Nov 2016 00:58:28 +0800 Subject: [PATCH 3/6] add test case --- src/compiler/codegen/events.js | 2 +- test/unit/features/directives/on.spec.js | 22 ++++++++++++++++++++++ test/unit/modules/compiler/codegen.spec.js | 8 ++++---- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/compiler/codegen/events.js b/src/compiler/codegen/events.js index 13320ab7b97..44308ffcc10 100644 --- a/src/compiler/codegen/events.js +++ b/src/compiler/codegen/events.js @@ -84,5 +84,5 @@ function genFilterCode (key: number | string): string { return `$event.keyCode!==${keyVal}` } const alias = keyCodes[key] - return `_k($event.keyCode, ${JSON.stringify(key)}${alias ? ',' + JSON.stringify(alias) : ''})` + return `_k($event.keyCode,${JSON.stringify(key)}${alias ? ',' + JSON.stringify(alias) : ''})` } 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)}}})}` ) }) From 04e46ccf3ae2a2a2911ad47ac9a1a73002b4ab6b Mon Sep 17 00:00:00 2001 From: defcc Date: Mon, 28 Nov 2016 01:00:19 +0800 Subject: [PATCH 4/6] update comment --- src/core/instance/render.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/instance/render.js b/src/core/instance/render.js index 915b1696f3e..cf77595771c 100644 --- a/src/core/instance/render.js +++ b/src/core/instance/render.js @@ -238,8 +238,8 @@ export function renderMixin (Vue: Class) { return data } - // expose v-on keyCodes - Vue.prototype._k = function getKeyCodes ( + // check v-on keyCodes + Vue.prototype._k = function checkKeyCodes ( eventKeyCode: number, key: string, buildinAlias: number | Array | void From 8ae764312aff39f90685d8a22972053e5374a55e Mon Sep 17 00:00:00 2001 From: defcc Date: Mon, 28 Nov 2016 01:19:42 +0800 Subject: [PATCH 5/6] update flow type --- src/core/instance/render.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/instance/render.js b/src/core/instance/render.js index cf77595771c..a4a0f7afedb 100644 --- a/src/core/instance/render.js +++ b/src/core/instance/render.js @@ -243,7 +243,7 @@ export function renderMixin (Vue: Class) { eventKeyCode: number, key: string, buildinAlias: number | Array | void - ): any { + ): boolean { const keyCodes = config.keyCodes[key] || buildinAlias if (Array.isArray(keyCodes)) { return keyCodes.indexOf(eventKeyCode) === -1 From 335ee2e9818bc754b93cc1211c75854335c1aeb2 Mon Sep 17 00:00:00 2001 From: defcc Date: Mon, 28 Nov 2016 01:30:13 +0800 Subject: [PATCH 6/6] update comment --- flow/component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flow/component.js b/flow/component.js index 74ce164ed16..f18406da6f6 100644 --- a/flow/component.js +++ b/flow/component.js @@ -104,7 +104,7 @@ 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 + // check custom keyCode _k: (eventKeyCode: number, key: string, buildinAlias: number | Array | void) => boolean; // allow dynamic method registration