react-khooks
v1.2.4
Published
This is a custom hook based on React keyboard events, integrating event queue management solutions
Downloads
15
Maintainers
Readme
react-khooks
Getting Started
📦 Install
$ npm i react-khooks --save
🔨 Usage
// 根据需要结构以下对应模块使用
import { useKeyEvent } from 'react-khooks'; //键盘hooks
import { emitter } from 'react-khooks'; //事件队列中心(单例)
这是一个基于React的键盘事件的自定义hooks,是基于公司的业务封装的,支持一个按键绑定多个事件(事件队列管理),只触发最新绑定的事件,队列顺序根据业务去维护,毕竟正常来说一个按键在某一时刻只会触发单一功能事件。(其实可以通过事件权重去托管给emitter本身去管理)
tips: 已重构为ts(菜鸡)版本,欢迎star和issue
| 参数 | 说明 | | --- | --- | | keyName | 键盘按键名key或keyCode,建议统一,必传(组合键使用+连接,如:ctrl+按键名,请注意和浏览器以及系统按键的冲突问题) | | callback | 回调函数,默认参数e为KeyboardEvent事件对象,必传 | | toolEventName | 自定义事件名称,作为该键盘事件队列中的唯一标识,必传 | | type | 键盘弹起或按下(keyup/keydown),默认keyup | | delayTime | 防抖/节流延迟时间,默认0为不使用节流/防抖 (如果使用keydown,建议设置) | | delayType | 1节流/2防抖,默认1 |
- 一般来说,你只需要传入三个属性:keyName(键盘按键名),callback(回调函数),toolEventName(自定义事件名)
- 支持复合键+按键和**复合键+复合键+按键的组合按键事件 (复合键是指ctrl/alt/shift)
- 你可以基于callback的默认参数KeyboardEvent根据该事件对象进行更多逻辑控制或完成更多复合按键
- useKeyEvent默认返回事件队列实例,这是一个单例,意味着你在任何地方返回的都是同一个emitter实例或者直接导入,以手动控制事件队列
基本用法:
import React, { useState, useCallback } from 'react';
import { useKeyEvent } from 'react-khooks';
export default () => {
const handleClick = () => {
alert('按键z触发');
};
useKeyEvent({ keyName: 'z', callback: handleClick, toolEventName: 'alert' });
return (
<div>
<div>按键z键弹出提示</div>
</div>
);
};
组合键(ctrl/alt/shift+按键):
- 回调接收默认参数(KeyboardEvent 事件对象)
import React, { useState, useCallback } from 'react';
import { useKeyEvent } from 'react-khooks';
export default () => {
const [num, setNum] = useState(0);
const handleClick = (e) => {
setNum(num + 1);
};
useKeyEvent({ keyName: `alt+v`, callback: handleClick, toolEventName: '增加num' });
useKeyEvent({ keyName: `ctrl+v`, callback: handleClick, toolEventName: '增加num' });
useKeyEvent({ keyName: `shift+v`, callback: handleClick, toolEventName: '增加num' });
return (
<div>
<div>按键ctrl/alt/shift+v增加num</div>
<span>num: {num}</span>
</div>
);
};
动态切换绑定热键:
import React, { useState, useCallback } from 'react';
import { useKeyEvent } from 'react-khooks';
export default () => {
const [num, setNum] = useState(0);
const [hotKey, setHotKey] = useState('m');
const handleClick = () => {
setNum(num + 1);
};
useKeyEvent({ keyName: hotKey, callback: handleClick, toolEventName: '修改num' });
return (
<div>
<div>按键{hotKey}键修改num</div>
<div>num: {num}</div>
<div>
<button onClick={() => setHotKey('n')}>切换为使用n键修改num</button>
</div>
</div>
);
};
节流/防抖
import React, { useState, useCallback } from 'react';
import { useKeyEvent } from 'react-khooks';
export default () => {
const [num, setNum] = useState(0);
const handleClick = useCallback(() => {
setNum(num + 1);
}, [num]);
useKeyEvent({
keyName: 'q',
callback: handleClick,
toolEventName: '长按q键修改num',
delayTime: 500,
type: 'keydown',
delayType: 1,
});
useKeyEvent({
keyName: 'w',
callback: handleClick,
toolEventName: '长按w键修改num',
delayTime: 500,
type: 'keydown',
delayType: 2,
});
return (
<div>
<div>节流:长按q键修改num(每500ms触发一次)</div>
<div>num: {num}</div>
<div>防抖:长按w键修改num(直到抬起触发一次)</div>
</div>
);
};
关于回调函数 callback 的处理强烈建议使用 useCallback,避免组件重新渲染时频繁订阅取消
- 使用 useCalback 内 setState 获取当前状态
import React, { useState, useCallback } from 'react';
import { useKeyEvent } from 'react-khooks';
export default () => {
const [num, setNum] = useState(0);
const handleClick = useCallback(() => {
setNum((num) => num + 1);
}, []);
useKeyEvent({ keyName: 'a', callback: handleClick, toolEventName: 'add' });
return (
<div>
设置快捷键 a 修改 useState 定义的 num 数据
<div>num: {num}</div>
</div>
);
};
- useCallback 依赖获取当前状态
import React, { useState, useCallback } from 'react';
import { useKeyEvent } from 'react-khooks';
export default () => {
const [num, setNum] = useState(0);
const handleClick = useCallback(() => {
setNum(num - 1);
}, [num]);
useKeyEvent({ keyName: 's', callback: handleClick, toolEventName: 'reduce' });
return (
<div>
设置快捷键 s 修改 useState 定义的 num 数据
<div>num: {num}</div>
</div>
);
};
- ~~不推荐(会导致组件重新渲染时频繁取消/订阅,性能差,虽然内部做了处理,避免这个问题,但是还是不推荐)~~
- 目前做了优化,组件重新渲染时不会频繁取消/订阅(虽然好像可以在回调中拿到最新的state,但还是推荐使用前门两种方式获取state)
import React, { useState, useCallback } from 'react';
import { useKeyEvent } from 'react-khooks';
export default () => {
const [num, setNum] = useState(0);
const handleClick = (param) => {
setNum(num + param);
};
useKeyEvent({ keyName: 'ctrl+x', callback: () => handleClick(1), toolEventName: 'add_2' });
useKeyEvent({ keyName: 'shift+x', callback: () => handleClick(-1), toolEventName: 'reduce_2' });
return (
<div>
<div>按键ctrl+x增加num</div>
<div>按键shift+x减小num</div>
<button onClick={() => handleClick(1)}> 加 1 </button>
<span>num: {num}</span>
<button onClick={() => handleClick(-1)}> 减 1 </button>
</div>
);
};
freezeAll/unfreezeAll:冻结/解冻所有键盘事件队列
import React, { useState, useCallback } from 'react';
import { useKeyEvent } from 'react-khooks';
export default () => {
const [num, setNum] = useState(0);
const handleClick = () => {
setNum((num) => num + 1);
};
const { emitter } = useKeyEvent({ keyName: 'f', callback: handleClick, toolEventName: 'add' });
// 你也可以直接 import { emitter } from 'react-khooks',因为这里的emitter始终是同一个实例
return (
<div>
<p>按下键盘f键修改num</p>
<span style={{ border: '1px solid #ccc' }} onClick={() => emitter.freezeAll()}>
冻 结
</span>
<div>num: {num}</div>
<span style={{ border: '1px solid #ccc' }} onClick={() => emitter.unfreezeAll()}>
解 冻
</span>
</div>
);
};