feat: add .exact event modifier (#5977)

Allow limiting the event to the exact system modifiers specified.
close #5976
This commit is contained in:
Nick Messing 2017-10-04 19:37:00 +03:00 committed by Evan You
parent e1da0d585c
commit 9734e878ec
4 changed files with 109 additions and 3 deletions

View File

@ -87,6 +87,14 @@ function genHandler (
if (keyCodes[key]) {
keys.push(key)
}
} else if (key === 'exact') {
const modifiers: ASTModifiers = (handler.modifiers: any)
genModifierCode += genGuard(
['ctrl', 'shift', 'alt', 'meta']
.filter(keyModifier => !modifiers[keyModifier])
.map(keyModifier => `$event.${keyModifier}Key`)
.join('||')
)
} else {
keys.push(key)
}

View File

@ -29,7 +29,7 @@ if (process.env.NODE_ENV !== 'production') {
Proxy.toString().match(/native code/)
if (hasProxy) {
const isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta')
const isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact')
config.keyCodes = new Proxy(config.keyCodes, {
set (target, key, value) {
if (isBuiltInModifier(key)) {

View File

@ -205,6 +205,96 @@ describe('Directive v-on', () => {
expect(spy).toHaveBeenCalled()
})
// ctrl, shift, alt, meta
it('should support system modifers', () => {
vm = new Vue({
el,
template: `
<div>
<input ref="ctrl" @keyup.ctrl="foo">
<input ref="shift" @keyup.shift="foo">
<input ref="alt" @keyup.alt="foo">
<input ref="meta" @keyup.meta="foo">
</div>
`,
methods: { foo: spy }
})
triggerEvent(vm.$refs.ctrl, 'keyup')
expect(spy.calls.count()).toBe(0)
triggerEvent(vm.$refs.ctrl, 'keyup', e => { e.ctrlKey = true })
expect(spy.calls.count()).toBe(1)
triggerEvent(vm.$refs.shift, 'keyup')
expect(spy.calls.count()).toBe(1)
triggerEvent(vm.$refs.shift, 'keyup', e => { e.shiftKey = true })
expect(spy.calls.count()).toBe(2)
triggerEvent(vm.$refs.alt, 'keyup')
expect(spy.calls.count()).toBe(2)
triggerEvent(vm.$refs.alt, 'keyup', e => { e.altKey = true })
expect(spy.calls.count()).toBe(3)
triggerEvent(vm.$refs.meta, 'keyup')
expect(spy.calls.count()).toBe(3)
triggerEvent(vm.$refs.meta, 'keyup', e => { e.metaKey = true })
expect(spy.calls.count()).toBe(4)
})
it('should support exact modifier', () => {
vm = new Vue({
el,
template: `
<div>
<input ref="ctrl" @keyup.exact="foo">
</div>
`,
methods: { foo: spy }
})
triggerEvent(vm.$refs.ctrl, 'keyup')
expect(spy.calls.count()).toBe(1)
triggerEvent(vm.$refs.ctrl, 'keyup', e => {
e.ctrlKey = true
})
expect(spy.calls.count()).toBe(1)
// should not trigger if has other system modifiers
triggerEvent(vm.$refs.ctrl, 'keyup', e => {
e.ctrlKey = true
e.altKey = true
})
expect(spy.calls.count()).toBe(1)
})
it('should support system modifers with exact', () => {
vm = new Vue({
el,
template: `
<div>
<input ref="ctrl" @keyup.ctrl.exact="foo">
</div>
`,
methods: { foo: spy }
})
triggerEvent(vm.$refs.ctrl, 'keyup')
expect(spy.calls.count()).toBe(0)
triggerEvent(vm.$refs.ctrl, 'keyup', e => {
e.ctrlKey = true
})
expect(spy.calls.count()).toBe(1)
// should not trigger if has other system modifiers
triggerEvent(vm.$refs.ctrl, 'keyup', e => {
e.ctrlKey = true
e.altKey = true
})
expect(spy.calls.count()).toBe(1)
})
it('should support number keyCode', () => {
vm = new Vue({
el,
@ -497,8 +587,8 @@ describe('Directive v-on', () => {
}).not.toThrow()
})
// GitHub Issue #5046
it('should support keyboard modifier', () => {
// Github Issue #5046
it('should support keyboard modifier for direction keys', () => {
const spyLeft = jasmine.createSpy()
const spyRight = jasmine.createSpy()
const spyUp = jasmine.createSpy()

View File

@ -312,6 +312,14 @@ describe('codegen', () => {
'<input @click.meta="onClick">',
`with(this){return _c('input',{on:{"click":function($event){if(!$event.metaKey)return null;onClick($event)}}})}`
)
assertCodegen(
'<input @click.exact="onClick">',
`with(this){return _c('input',{on:{"click":function($event){if($event.ctrlKey||$event.shiftKey||$event.altKey||$event.metaKey)return null;onClick($event)}}})}`
)
assertCodegen(
'<input @click.ctrl.exact="onClick">',
`with(this){return _c('input',{on:{"click":function($event){if(!$event.ctrlKey)return null;if($event.shiftKey||$event.altKey||$event.metaKey)return null;onClick($event)}}})}`
)
})
it('generate events with multiple modifiers', () => {