Skip to content

Commit 9734e87

Browse files
nickmessingyyx990803
authored andcommitted
feat: add .exact event modifier (#5977)
Allow limiting the event to the exact system modifiers specified. close #5976
1 parent e1da0d5 commit 9734e87

File tree

4 files changed

+109
-3
lines changed

4 files changed

+109
-3
lines changed

src/compiler/codegen/events.js

+8
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,14 @@ function genHandler (
8787
if (keyCodes[key]) {
8888
keys.push(key)
8989
}
90+
} else if (key === 'exact') {
91+
const modifiers: ASTModifiers = (handler.modifiers: any)
92+
genModifierCode += genGuard(
93+
['ctrl', 'shift', 'alt', 'meta']
94+
.filter(keyModifier => !modifiers[keyModifier])
95+
.map(keyModifier => `$event.${keyModifier}Key`)
96+
.join('||')
97+
)
9098
} else {
9199
keys.push(key)
92100
}

src/core/instance/proxy.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ if (process.env.NODE_ENV !== 'production') {
2929
Proxy.toString().match(/native code/)
3030

3131
if (hasProxy) {
32-
const isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta')
32+
const isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact')
3333
config.keyCodes = new Proxy(config.keyCodes, {
3434
set (target, key, value) {
3535
if (isBuiltInModifier(key)) {

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

+92-2
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,96 @@ describe('Directive v-on', () => {
205205
expect(spy).toHaveBeenCalled()
206206
})
207207

208+
// ctrl, shift, alt, meta
209+
it('should support system modifers', () => {
210+
vm = new Vue({
211+
el,
212+
template: `
213+
<div>
214+
<input ref="ctrl" @keyup.ctrl="foo">
215+
<input ref="shift" @keyup.shift="foo">
216+
<input ref="alt" @keyup.alt="foo">
217+
<input ref="meta" @keyup.meta="foo">
218+
</div>
219+
`,
220+
methods: { foo: spy }
221+
})
222+
223+
triggerEvent(vm.$refs.ctrl, 'keyup')
224+
expect(spy.calls.count()).toBe(0)
225+
triggerEvent(vm.$refs.ctrl, 'keyup', e => { e.ctrlKey = true })
226+
expect(spy.calls.count()).toBe(1)
227+
228+
triggerEvent(vm.$refs.shift, 'keyup')
229+
expect(spy.calls.count()).toBe(1)
230+
triggerEvent(vm.$refs.shift, 'keyup', e => { e.shiftKey = true })
231+
expect(spy.calls.count()).toBe(2)
232+
233+
triggerEvent(vm.$refs.alt, 'keyup')
234+
expect(spy.calls.count()).toBe(2)
235+
triggerEvent(vm.$refs.alt, 'keyup', e => { e.altKey = true })
236+
expect(spy.calls.count()).toBe(3)
237+
238+
triggerEvent(vm.$refs.meta, 'keyup')
239+
expect(spy.calls.count()).toBe(3)
240+
triggerEvent(vm.$refs.meta, 'keyup', e => { e.metaKey = true })
241+
expect(spy.calls.count()).toBe(4)
242+
})
243+
244+
it('should support exact modifier', () => {
245+
vm = new Vue({
246+
el,
247+
template: `
248+
<div>
249+
<input ref="ctrl" @keyup.exact="foo">
250+
</div>
251+
`,
252+
methods: { foo: spy }
253+
})
254+
255+
triggerEvent(vm.$refs.ctrl, 'keyup')
256+
expect(spy.calls.count()).toBe(1)
257+
258+
triggerEvent(vm.$refs.ctrl, 'keyup', e => {
259+
e.ctrlKey = true
260+
})
261+
expect(spy.calls.count()).toBe(1)
262+
263+
// should not trigger if has other system modifiers
264+
triggerEvent(vm.$refs.ctrl, 'keyup', e => {
265+
e.ctrlKey = true
266+
e.altKey = true
267+
})
268+
expect(spy.calls.count()).toBe(1)
269+
})
270+
271+
it('should support system modifers with exact', () => {
272+
vm = new Vue({
273+
el,
274+
template: `
275+
<div>
276+
<input ref="ctrl" @keyup.ctrl.exact="foo">
277+
</div>
278+
`,
279+
methods: { foo: spy }
280+
})
281+
282+
triggerEvent(vm.$refs.ctrl, 'keyup')
283+
expect(spy.calls.count()).toBe(0)
284+
285+
triggerEvent(vm.$refs.ctrl, 'keyup', e => {
286+
e.ctrlKey = true
287+
})
288+
expect(spy.calls.count()).toBe(1)
289+
290+
// should not trigger if has other system modifiers
291+
triggerEvent(vm.$refs.ctrl, 'keyup', e => {
292+
e.ctrlKey = true
293+
e.altKey = true
294+
})
295+
expect(spy.calls.count()).toBe(1)
296+
})
297+
208298
it('should support number keyCode', () => {
209299
vm = new Vue({
210300
el,
@@ -497,8 +587,8 @@ describe('Directive v-on', () => {
497587
}).not.toThrow()
498588
})
499589

500-
// GitHub Issue #5046
501-
it('should support keyboard modifier', () => {
590+
// Github Issue #5046
591+
it('should support keyboard modifier for direction keys', () => {
502592
const spyLeft = jasmine.createSpy()
503593
const spyRight = jasmine.createSpy()
504594
const spyUp = jasmine.createSpy()

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

+8
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,14 @@ describe('codegen', () => {
312312
'<input @click.meta="onClick">',
313313
`with(this){return _c('input',{on:{"click":function($event){if(!$event.metaKey)return null;onClick($event)}}})}`
314314
)
315+
assertCodegen(
316+
'<input @click.exact="onClick">',
317+
`with(this){return _c('input',{on:{"click":function($event){if($event.ctrlKey||$event.shiftKey||$event.altKey||$event.metaKey)return null;onClick($event)}}})}`
318+
)
319+
assertCodegen(
320+
'<input @click.ctrl.exact="onClick">',
321+
`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)}}})}`
322+
)
315323
})
316324

317325
it('generate events with multiple modifiers', () => {

0 commit comments

Comments
 (0)