Browse Source

fix v-on .left .right compat with keyboard events (fix #5046)

dev
Evan You 8 years ago
parent
commit
3294eba5a5
  1. 14
      src/compiler/codegen/events.js
  2. 43
      test/unit/features/directives/on.spec.js
  3. 10
      test/unit/modules/compiler/codegen.spec.js

14
src/compiler/codegen/events.js

@ -29,9 +29,9 @@ const modifierCode: { [key: string]: string } = {
shift: genGuard(`!$event.shiftKey`),
alt: genGuard(`!$event.altKey`),
meta: genGuard(`!$event.metaKey`),
left: genGuard(`$event.button !== 0`),
middle: genGuard(`$event.button !== 1`),
right: genGuard(`$event.button !== 2`)
left: genGuard(`'button' in $event && $event.button !== 0`),
middle: genGuard(`'button' in $event && $event.button !== 1`),
right: genGuard(`'button' in $event && $event.button !== 2`)
}
export function genHandlers (events: ASTElementHandlers, native?: boolean): string {
@ -60,12 +60,16 @@ function genHandler (
for (const key in handler.modifiers) {
if (modifierCode[key]) {
code += modifierCode[key]
// left/right
if (keyCodes[key]) {
keys.push(key)
}
} else {
keys.push(key)
}
}
if (keys.length) {
code = genKeyFilter(keys) + code
code += genKeyFilter(keys)
}
const handlerCode = simplePathRE.test(handler.value)
? handler.value + '($event)'
@ -75,7 +79,7 @@ function genHandler (
}
function genKeyFilter (keys: Array<string>): string {
return `if(${keys.map(genFilterCode).join('&&')})return null;`
return `if(!('button' in $event)&&${keys.map(genFilterCode).join('&&')})return null;`
}
function genFilterCode (key: string): string {

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

@ -266,6 +266,7 @@ describe('Directive v-on', () => {
e.keyCode = 1
})
expect(spy).toHaveBeenCalled()
Vue.config.keyCodes = Object.create(null)
})
it('should override build-in keyCode', () => {
@ -288,6 +289,7 @@ describe('Directive v-on', () => {
e.keyCode = 40
})
expect(spy).toHaveBeenCalledTimes(3)
Vue.config.keyCodes = Object.create(null)
})
it('should bind to a child component', () => {
@ -483,4 +485,45 @@ describe('Directive v-on', () => {
triggerEvent(vm.$el, 'click')
}).not.toThrow()
})
// Github Issue #5046
it('should support keyboard modifier', () => {
const spyLeft = jasmine.createSpy()
const spyRight = jasmine.createSpy()
const spyUp = jasmine.createSpy()
const spyDown = jasmine.createSpy()
vm = new Vue({
el,
template: `
<div>
<input ref="left" @keydown.left="foo"></input>
<input ref="right" @keydown.right="foo1"></input>
<input ref="up" @keydown.up="foo2"></input>
<input ref="down" @keydown.down="foo3"></input>
</div>
`,
methods: {
foo: spyLeft,
foo1: spyRight,
foo2: spyUp,
foo3: spyDown
}
})
triggerEvent(vm.$refs.left, 'keydown', e => { e.keyCode = 37 })
triggerEvent(vm.$refs.left, 'keydown', e => { e.keyCode = 39 })
triggerEvent(vm.$refs.right, 'keydown', e => { e.keyCode = 39 })
triggerEvent(vm.$refs.right, 'keydown', e => { e.keyCode = 38 })
triggerEvent(vm.$refs.up, 'keydown', e => { e.keyCode = 38 })
triggerEvent(vm.$refs.up, 'keydown', e => { e.keyCode = 37 })
triggerEvent(vm.$refs.down, 'keydown', e => { e.keyCode = 40 })
triggerEvent(vm.$refs.down, 'keydown', e => { e.keyCode = 39 })
expect(spyLeft.calls.count()).toBe(1)
expect(spyRight.calls.count()).toBe(1)
expect(spyUp.calls.count()).toBe(1)
expect(spyDown.calls.count()).toBe(1)
})
})

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

@ -229,27 +229,27 @@ describe('codegen', () => {
it('generate events with keycode', () => {
assertCodegen(
'<input @input.enter="onInput">',
`with(this){return _c('input',{on:{"input":function($event){if(_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))return null;onInput($event)}}})}`
)
// multiple keycodes (delete)
assertCodegen(
'<input @input.delete="onInput">',
`with(this){return _c('input',{on:{"input":function($event){if(_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]))return null;onInput($event)}}})}`
)
// multiple keycodes (chained)
assertCodegen(
'<input @keydown.enter.delete="onInput">',
`with(this){return _c('input',{on:{"keydown":function($event){if(_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)&&_k($event.keyCode,"delete",[8,46]))return null;onInput($event)}}})}`
)
// number keycode
assertCodegen(
'<input @input.13="onInput">',
`with(this){return _c('input',{on:{"input":function($event){if($event.keyCode!==13)return null;onInput($event)}}})}`
`with(this){return _c('input',{on:{"input":function($event){if(!('button' in $event)&&$event.keyCode!==13)return null;onInput($event)}}})}`
)
// custom keycode
assertCodegen(
'<input @input.custom="onInput">',
`with(this){return _c('input',{on:{"input":function($event){if(_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"))return null;onInput($event)}}})}`
)
})

Loading…
Cancel
Save