keydown,keyup,keypress
事件默认是给页面上可以聚焦的元素绑定键盘事件,例如input输入框,点击输入框即代表聚焦在该元素上。那么想要给div或者其他不能聚焦的元素上使用键盘事件怎么处理呢?这里用到tabindex属性。
它接受一个整数作为值,具有不同的结果,具体取决于整数的值:
- tabindex=负值 (通常是 tabindex=“-1”),表示元素是可聚焦的,但是不能通过键盘导航来访问到该元素,用 JS
做页面小组件内部键盘导航的时候非常有用。 - tabindex=“0” ,表示元素是可聚焦的,并且可以通过键盘导航来聚焦到该元素,它的相对顺序是当前处于的 DOM 结构来决定的。
- tabindex=正值,表示元素是可聚焦的,并且可以通过键盘导航来访问到该元素;它的相对顺序按照 tabindex
的数值递增而滞后获焦。如果多个元素拥有相同的 tabindex,它们的相对顺序按照他们在当前 DOM 中的先后顺序决定。
<div class="key-even" id="editor" tabindex="-1">
keyDown
</div>
添加上 tabindex 属性后,此时div表示可以聚焦,但是想要触发键盘事件还需要调用 dom 的 focus() 方法,表示页面聚焦在该元素上,这样就可以触发键盘事件了。
const dom = document.getElementById('editor')
dom.addEventListener('click', this.domClick(dom))
dom.addEventListener('keydown', this.keyDown)
domClick(dom) {
dom.focus()
},
keyDown(e) {
console.log(e.keyCode)
}
绑定事件的方式可以改变,主要是讲述 tabindex 属性的用法及作用。
el-Cascader 源码解读:最后一张图片中,li中绑定的tabindex,使的li可以聚焦,
packages/cascader-panel/src/cascader-panel.vue
<template>
<div
:class="[
'el-cascader-panel',
border && 'is-bordered'
]"
@keydown="handleKeyDown">
<span>这个地址:element-ui/packages/cascader-panel</span>
<cascader-menu
ref="menu"
v-for="(menu, index) in menus"
:index="index"
:key="index"
:nodes="menu"></cascader-menu>
</div>
</template>
handleKeyDown(e) {
console.log('操作键盘是这里---》', e.target)
const { target, keyCode } = e;
switch (keyCode) {
case KeyCode.up:
const prev = getSibling(target, -1);
focusNode(prev);
break;
case KeyCode.down:
const next = getSibling(target, 1);
focusNode(next);
break;
case KeyCode.left:
const preMenu = this.$refs.menu[getMenuIndex(target) - 1];
if (preMenu) {
const expandedNode = preMenu.$el.querySelector('.el-cascader-node[aria-expanded="true"]');
focusNode(expandedNode);
}
break;
case KeyCode.right:
const nextMenu = this.$refs.menu[getMenuIndex(target) + 1];
if (nextMenu) {
const firstNode = nextMenu.$el.querySelector('.el-cascader-node[tabindex="-1"]');
focusNode(firstNode);
}
break;
case KeyCode.enter:
checkNode(target);
break;
case KeyCode.esc:
case KeyCode.tab:
this.$emit('close');
break;
default:
return;
}
},
packages/cascader-panel/src/cascader-node.vue