最近,公司项目中要做新的需求,其中最主要的功能要使用鼠标和键盘,因此我进行了相关的调研,并将我调研的结果写成笔记作为总结,也希望可以帮助到其他人。
首先我们来看一下在实际应用中常用的事件
- 鼠标事件:
- onclick: 鼠标点击事件
- ondblclick: 鼠标双击事件
- onmousedown: 鼠标上的按钮被按下了
- onmouseup: 鼠标按下后松开时触发的事件
- onmousemove: 鼠标移动时触发的事件
- onmouseout: 鼠标离开监听该事件的元素或子元素时触发的事件
- onmouseover: 鼠标移动到监听该事件的元素或子元素时触发的事件
- onmousewheel: 鼠标滚轮事件,一般使用onscroll事件
鼠标事件触发时参数 event 为 MouseEvent 对象类型:
- type: 事件类型,如 mousemove 或者 mousedown
- button: 整型,触发鼠标事件时按下的按钮编号
- buttons: 整型,触发鼠标事件时弹起来的按钮编号
- clientX: 鼠标指针在 DOM 内容区的 X 坐标
- clientY:鼠标指针在 DOM 内容区的 Y 坐标
- offsetX: 鼠标指针相对父节点填充边缘的 X 坐标
- offsetY: 鼠标指针相对父节点填充边缘的 Y 坐标
- screenX: 鼠标指针在全局屏幕的 X 坐标
- screenY: 鼠标指针在全局屏幕的 Y 坐标
- pageX: 鼠标指针在整个 DOM 内容(包括分页)的 X 坐标
- pageY: 鼠标指针在整个 DOM 内容(包括分页)的 Y 坐标
- altKey: 布尔值,表示此时的 alt 键是否也按下
- ctrlKey: 布尔值,表示此时的 ctrl 键是否也按下
- shiftKey: 布尔值,表示此时的 shift 键是否也按下
- metaKey: 布尔值,windows 平台表示 Window 键是否同时按下,mac 表示 Command 键是否同时按下
通过鼠标事件的 event 属性,可以获取鼠标点击的位置,鼠标点击时是否按住 ctrl 等
- 键盘事件:
- onkeydown: 键盘按下这个动作(按下键盘)
- onkeypress: 键盘被按住(一直按着键盘不动)
- onkeyup: 键盘被弹起(松开键盘)
键盘按下的 event 参数,该参数为 KeyboardEvent 事件对象:
- type: 事件类型,如 keydown 或者 keyup
- key: 表示按下的键盘内容是什么即键值,按下字母 p 时,值为 p
- code: 表示键盘代码,按下字母 p 时,值为 KeyP
- keyCode: 整数,表示键码,每个键都有唯一的键码,字母 p 的键码为 80
- altKey: 布尔值,表示此时的 alt 键是否也按下
- ctrlKey: 布尔值,表示此时的 ctrl 键是否也按下
- shiftKey: 布尔值,表示此时的 shift 键是否也按下
- metaKey: 布尔值,windows 平台表示 Window 键是否同时按下,mac 表示 Command 键是否同时按下
- repeat: 布尔值,如果一个键一直被按着,则其值为 true,表示重复
可以通过检查这些属性来判断用户按下的是什么键,以及 ctrl 和 alt 等键是否同时按下。
我们下面来看看实际应用的场景
- 在一个项目中,我们通常需要判断当前网页被点击的是哪一个元素,这时我们可以通过监听鼠标事件,代码如下:
import React, { memo, useCallback, useEffect } from 'react';
import { List, Typography, Divider, Table, Tag } from 'antd';
const data = [
'Racing car sprays burning fuel into crowd.',
'Japanese princess to wed commoner.',
'Australian walks 100km after outback crash.',
'Man charged over missing wedding girl.',
'Los Angeles battles huge wildfires.',
];
function demo() {
const handleMounseDown = useCallback((e) => {
/** 点击了哪个元素 */
let targ;
// 事件具体指向的事件源
if(e.target) {
targ = e.target;
} else if (e.srcElement) {
targ = e.srcElement;
}
if(targ.nodeType === 3) {
targ = targ.parentNode;
}
const tName = targ.tagName;
console.log("你点击了 " , tName , "元素"); // li
})
return(
<div onMouseDown={handleMounseDown}>
<List
header={<div>Header</div>}
footer={<div>Footer</div>}
bordered
dataSource={data}
renderItem={item => (
<List.Item>
<Typography.Text mark>[ITEM]</Typography.Text> {item}
</List.Item>
)}
/>
</div>
)
}
export default memo(demo);
通过上述的代码,我们就可以知道当前被点击的元素了。
现在我们知道了如何获取点击的元素,那么我们如何判断鼠标的哪个按键正在被点击呢?还是使用上面的页面,只不过我们在鼠标事件的处理方法中增加了判断鼠标按键的逻辑。
- 如何判断鼠标哪个按健正在被点击
const handleMounseDown = useCallback((e) => {
/** 判断鼠标按键 */
const pressMouseKey = e.button;
const showMouseKey = pressMouseKey === 2 ? '右键' : '左键';
console.log('鼠标按下的按键:', showMouseKey, e.button);
})
通过这段代码发现,我们可以在鼠标事件中获取 button 的值,通过它去判断是左键还是右键。
- 有的时侯,在实际应用中,我们通常也会去监测当前键盘按下的是否是 shift 键, 我们仍使用上面的页面:
useEffect(() => {
document.onkeydown = (e) => {
/** 判断是否按下 shift 键 */
const isPressShift = e.shiftKey;
console.log('是否按了shift键:', isPressShift);
})
- 当然,我们也可能需要检测是否按下 ctrl / command 键:
useEffect(() => {
document.onkeydown = (e) => {
/** 判断是否按下 ctrl / command 键 */
const isPressCtrl = e.ctrlKey;
const isPressCommand = e.metaKey;
console.log('是否按下ctrl键: ', isPressCtrl, '; 是否按下command键: ', isPressCommand, e);
})
- 有时,我们也需要获取被按下的键盘任意键的 unicode 码:
document.onkeydown = (e) => {
/** 按下键的 unicode 码 */
const pressKeyCode = document.all ? e.keyCode : e.which;
console.log('当前按下键的unicode码: ', pressKeyCode );
}
- 如果项目中需要使用按键去执行删除操作时,我们还需要监测 Backspace / Delete 键:
useEffect(() => {
document.onkeydown = (e) => {
/** 判断是否按下退格键/Delete键 */
const pressKeyCode = document.all ? e.keyCode : e.which;
const isPressBackSpace = pressKeyCode === 8;
const isPressDelete = pressKeyCode === 46;
console.log('是否按下退格键', isPressBackSpace, '; 是否按下Delete键:', isPressDelete, pressKeyCode);
})
- 我们还可能通过键盘去执行 ctrl + c / ctrl + v / command + c / command + v:
useEffect(() => {
document.onkeydown = (e) => {
const pressKeyCode = document.all ? e.keyCode : e.which;
/** 判断是否按下 ctrl / command 键 */
const isPressCtrl = e.ctrlKey;
const isPressCommand = e.metaKey;
console.log('是否按下ctrl键: ', isPressCtrl, '; 是否按下command键: ', isPressCommand, e);
/** 判断是否按下 ctrl + c / ctrl + v 或 command + c / command + v */
if(isPressCtrl || isPressCommand) {
if(pressKeyCode === 67) {
console.log('按下ctrl+c/command+c');
}
if(pressKeyCode === 86) {
console.log('按下ctrl+v/command+v');
}
}
}
})
- 我们有时也可能会禁用 ctrl + c / ctrl + v,这时我们可以使用:
document.oncontextmenu = function(){
return false;
}
document.onkeydown = function(){
if (event.ctrlKey && window.event.keyCode === 67){
return false;
}
if (event.ctrlKey && window.event.keyCode === 86){
return false;
}
}
document.body.oncopy = function (){
return false;
}
document.onselectstart = function(){
//return false;
}
- 那么,如何使用自定义的右键菜单呢?
import React, { memo, useCallback, useEffect } from 'react';
import { List, Typography, Divider, Tag } from 'antd';
import style from './index.less';
const data = [
'Racing car sprays burning fuel into crowd.',
'Japanese princess to wed commoner.',
'Australian walks 100km after outback crash.',
'Man charged over missing wedding girl.',
'Los Angeles battles huge wildfires.',
];
function Shift() {
const handleOnContextMenu = useCallback((e) => {
// 取消默认的浏览器自带右键
e.preventDefault();
const menu = document.querySelector('#menu');
menu.style.left = `${e.clientX}px`;
menu.style.top = `${e.clientY}px`;
menu.style.width = '125px';
menu.style.height = '125px';
})
return(
<div>
<div onContextMenu={handleOnContextMenu}>
<List
header={<div>Header</div>}
footer={<div>Footer</div>}
bordered
dataSource={data}
renderItem={item => (
<List.Item>
<Typography.Text mark>[ITEM]</Typography.Text> {item}
</List.Item>
)}
/>
</div>
<div id="menu" className={style.menuContainer}>
<div className={style.menu}>功能1</div>
<div className={style.menu}>功能2</div>
<div className={style.menu}>功能3</div>
<div className={style.menu}>功能4</div>
<div className={style.menu}>功能5</div>
</div>
</div>
)
}
export default memo(Shift);
现在我们已经可以自定义右键菜单了,而且只修改了列表右键的菜单,当点击列表以外的区域都会出现自带的右键菜单。
最后附上键码值,方便大家查阅和使用。
keycode 8 = BackSpace BackSpace
keycode 9 = Tab Tab
keycode 12 = Clear
keycode 13 = Enter
keycode 16 = Shift_L
keycode 17 = Control_L
keycode 18 = Alt_L
keycode 19 = Pause
keycode 20 = Caps_Lock
keycode 27 = Escape Escape
keycode 32 = space space
keycode 33 = Prior
keycode 34 = Next
keycode 35 = End
keycode 36 = Home
keycode 37 = Left
keycode 38 = Up
keycode 39 = Right
keycode 40 = Down
keycode 41 = Select
keycode 42 = Print
keycode 43 = Execute
keycode 45 = Insert
keycode 46 = Delete
keycode 47 = Help
keycode 48 = 0 equal braceright
keycode 49 = 1 exclam onesuperior
keycode 50 = 2 quotedbl twosuperior
keycode 51 = 3 section threesuperior
keycode 52 = 4 dollar
keycode 53 = 5 percent
keycode 54 = 6 ampersand
keycode 55 = 7 slash braceleft
keycode 56 = 8 parenleft bracketleft
keycode 57 = 9 parenright bracketright
keycode 65 = a A
keycode 66 = b B
keycode 67 = c C
keycode 68 = d D
keycode 69 = e E EuroSign
keycode 70 = f F
keycode 71 = g G
keycode 72 = h H
keycode 73 = i I
keycode 74 = j J
keycode 75 = k K
keycode 76 = l L
keycode 77 = m M mu
keycode 78 = n N
keycode 79 = o O
keycode 80 = p P
keycode 81 = q Q at
keycode 82 = r R
keycode 83 = s S
keycode 84 = t T
keycode 85 = u U
keycode 86 = v V
keycode 87 = w W
keycode 88 = x X
keycode 89 = y Y
keycode 90 = z Z
keycode 96 = KP_0 KP_0
keycode 97 = KP_1 KP_1
keycode 98 = KP_2 KP_2
keycode 99 = KP_3 KP_3
keycode 100 = KP_4 KP_4
keycode 101 = KP_5 KP_5
keycode 102 = KP_6 KP_6
keycode 103 = KP_7 KP_7
keycode 104 = KP_8 KP_8
keycode 105 = KP_9 KP_9
keycode 106 = KP_Multiply KP_Multiply
keycode 107 = KP_Add KP_Add
keycode 108 = KP_Separator KP_Separator
keycode 109 = KP_Subtract KP_Subtract
keycode 110 = KP_Decimal KP_Decimal
keycode 111 = KP_Divide KP_Divide
keycode 112 = F1
keycode 113 = F2
keycode 114 = F3
keycode 115 = F4
keycode 116 = F5
keycode 117 = F6
keycode 118 = F7
keycode 119 = F8
keycode 120 = F9
keycode 121 = F10
keycode 122 = F11
keycode 123 = F12
keycode 124 = F13
keycode 125 = F14
keycode 126 = F15
keycode 127 = F16
keycode 128 = F17
keycode 129 = F18
keycode 130 = F19
keycode 131 = F20
keycode 132 = F21
keycode 133 = F22
keycode 134 = F23
keycode 135 = F24
keycode 136 = Num_Lock
keycode 137 = Scroll_Lock
keycode 187 = acute grave
keycode 188 = comma semicolon
keycode 189 = minus underscore
keycode 190 = period colon
keycode 192 = numbersign apostrophe
keycode 210 = plusminus hyphen macron
keycode 211 =
keycode 212 = copyright registered
keycode 213 = guillemotleft guillemotright
keycode 214 = masculine ordfeminine
keycode 215 = ae AE
keycode 216 = cent yen
keycode 217 = questiondown exclamdown
keycode 218 = onequarter onehalf threequarters
keycode 220 = less greater bar
keycode 221 = plus asterisk asciitilde
keycode 227 = multiply division
keycode 228 = acircumflex Acircumflex
keycode 229 = ecircumflex Ecircumflex
keycode 230 = icircumflex Icircumflex
keycode 231 = ocircumflex Ocircumflex
keycode 232 = ucircumflex Ucircumflex
keycode 233 = ntilde Ntilde
keycode 234 = yacute Yacute
keycode 235 = oslash Ooblique
keycode 236 = aring Aring
keycode 237 = ccedilla Ccedilla
keycode 238 = thorn THORN
keycode 239 = eth ETH
keycode 240 = diaeresis cedilla currency
keycode 241 = agrave Agrave atilde Atilde
keycode 242 = egrave Egrave
keycode 243 = igrave Igrave
keycode 244 = ograve Ograve otilde Otilde
keycode 245 = ugrave Ugrave
keycode 246 = adiaeresis Adiaeresis
keycode 247 = ediaeresis Ediaeresis
keycode 248 = idiaeresis Idiaeresis
keycode 249 = odiaeresis Odiaeresis
keycode 250 = udiaeresis Udiaeresis
keycode 251 = ssharp question backslash
keycode 252 = asciicircum degree
keycode 253 = 3 sterling
keycode 254 = Mode_switch