Skip to content

Commit

Permalink
Support mutliple keys for keycode (#4328)
Browse files Browse the repository at this point in the history
* support mutliple keys for keycode

* update flow type

* add test case

* update comment

* update flow type

* update comment
  • Loading branch information
defcc authored and yyx990803 committed Nov 30, 2016
1 parent 9215ff0 commit 6ea9a4d
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 23 deletions.
4 changes: 2 additions & 2 deletions flow/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ declare interface Component {
_t: (name: string, fallback: ?Array<VNode>, props: ?Object) => ?Array<VNode>;
// 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<number> | void) => boolean;

// allow dynamic method registration
[key: string]: any
Expand Down
23 changes: 9 additions & 14 deletions src/compiler/codegen/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,15 @@ function genHandler (
}

function genKeyFilter (keys: Array<string>): 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) : ''})`
}
15 changes: 12 additions & 3 deletions src/core/instance/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,18 @@ export function renderMixin (Vue: Class<Component>) {
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<number> | void
): boolean {
const keyCodes = config.keyCodes[key] || buildinAlias
if (Array.isArray(keyCodes)) {
return keyCodes.indexOf(eventKeyCode) === -1
} else {
return keyCodes !== eventKeyCode
}
}
}

Expand Down
22 changes: 22 additions & 0 deletions test/unit/features/directives/on.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,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: `<input @keyup.up="foo" @keyup.down="foo">`,
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: '<span>Hello</span>'
Expand Down
8 changes: 4 additions & 4 deletions test/unit/modules/compiler/codegen.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,17 +224,17 @@ describe('codegen', () => {
it('generate events with keycode', () => {
assertCodegen(
'<input @input.enter="onInput">',
`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(
'<input @input.delete="onInput">',
`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(
'<input @keydown.enter.delete="onInput">',
`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(
Expand All @@ -244,7 +244,7 @@ describe('codegen', () => {
// custom keycode
assertCodegen(
'<input @input.custom="onInput">',
`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)}}})}`
)
})

Expand Down

0 comments on commit 6ea9a4d

Please sign in to comment.