鼠标和键盘小结

最近,公司项目中要做新的需求,其中最主要的功能要使用鼠标和键盘,因此我进行了相关的调研,并将我调研的结果写成笔记作为总结,也希望可以帮助到其他人。

首先我们来看一下在实际应用中常用的事件

  1. 鼠标事件:
  • 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 等

  1. 键盘事件:
  • 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 等键是否同时按下。

我们下面来看看实际应用的场景

  1. 在一个项目中,我们通常需要判断当前网页被点击的是哪一个元素,这时我们可以通过监听鼠标事件,代码如下:
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);

通过上述的代码,我们就可以知道当前被点击的元素了。

现在我们知道了如何获取点击的元素,那么我们如何判断鼠标的哪个按键正在被点击呢?还是使用上面的页面,只不过我们在鼠标事件的处理方法中增加了判断鼠标按键的逻辑。

  1. 如何判断鼠标哪个按健正在被点击
  const handleMounseDown = useCallback((e) => {
    /** 判断鼠标按键 */
    const pressMouseKey = e.button;
    const showMouseKey = pressMouseKey === 2 ? '右键' : '左键';
    console.log('鼠标按下的按键:', showMouseKey, e.button);
  })

通过这段代码发现,我们可以在鼠标事件中获取 button 的值,通过它去判断是左键还是右键。

  1. 有的时侯,在实际应用中,我们通常也会去监测当前键盘按下的是否是 shift 键, 我们仍使用上面的页面:
  useEffect(() => {
    document.onkeydown = (e) => {
      /** 判断是否按下 shift 键 */
      const isPressShift = e.shiftKey;
      console.log('是否按了shift键:', isPressShift);
  })
  1. 当然,我们也可能需要检测是否按下 ctrl / command 键:
  useEffect(() => {
    document.onkeydown = (e) => {
      /** 判断是否按下 ctrl / command 键 */
      const isPressCtrl = e.ctrlKey;
      const isPressCommand = e.metaKey;
      console.log('是否按下ctrl键: ', isPressCtrl, '; 是否按下command键: ', isPressCommand, e);
  })
  1. 有时,我们也需要获取被按下的键盘任意键的 unicode 码:
document.onkeydown = (e) => {
      /** 按下键的 unicode 码 */
      const pressKeyCode = document.all ? e.keyCode : e.which;
      console.log('当前按下键的unicode码: ', pressKeyCode );
    }
  1. 如果项目中需要使用按键去执行删除操作时,我们还需要监测 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);
  })
  1. 我们还可能通过键盘去执行 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');
        }
      }
    }
  })
  1. 我们有时也可能会禁用 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; 
}
  1. 那么,如何使用自定义的右键菜单呢?
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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352