20260822171825
This commit is contained in:
1 parent
c43b4c8364
commit
27a32b313d
187 files changed
+34869
-4741
No files matched your search
@@ -0,0 +1,56 @@
|
||||
import { onBeforeUnmount, onMounted } from 'vue'
|
||||
|
||||
// 输入态判断:焦点在 input / textarea / 可编辑区域
|
||||
function isTypingTarget(e) {
|
||||
const el = e.target
|
||||
return !!el && (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.isContentEditable)
|
||||
}
|
||||
|
||||
// 快捷键匹配:精确匹配(未声明的修饰符按下则不匹配)
|
||||
function matches(e, s) {
|
||||
if (e.key.toLowerCase() !== String(s.key).toLowerCase()) return false
|
||||
// 主修饰键:声明了 mod / ctrl / meta 中任一 → 要求 Ctrl 或 Meta 按下
|
||||
const needsMod = s.mod === true || s.ctrl === true || s.meta === true
|
||||
const modPressed = e.ctrlKey || e.metaKey
|
||||
if (needsMod !== modPressed) return false
|
||||
// alt / shift 精确匹配(未声明即要求未按下)
|
||||
if (!!s.alt !== e.altKey) return false
|
||||
if (!!s.shift !== e.shiftKey) return false
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 全局键盘快捷键注册(可组合、可复用)。
|
||||
*
|
||||
* 用法(在任意组件 setup 顶层调用):
|
||||
* useHotkeys([
|
||||
* { key: 's', mod: true, ignoreWhenTyping: false, handler: save }, // Ctrl/Cmd + S
|
||||
* { key: '/', handler: focusSearch }, // 单独键(无修饰符)
|
||||
* { key: 'r', alt: true, handler: reload }, // Alt + R
|
||||
* ])
|
||||
*
|
||||
* 修饰符语义(精确匹配,未声明的修饰符按下则不匹配):
|
||||
* mod —— 主修饰键:Ctrl 或 Meta(Cmd)任一(跨平台主修饰键)
|
||||
* ctrl / meta / alt / shift —— 单独指定(与 mod 可叠加,如 { key: 's', mod: true, shift: true })
|
||||
*
|
||||
* 其他选项:
|
||||
* ignoreWhenTyping(默认 true)—— 焦点在 input / textarea / 可编辑区域时忽略;
|
||||
* 组合保存类快捷键(如 Ctrl+S)通常传 false,保证输入时也能保存。
|
||||
* handler(e) —— 触发回调,默认已 preventDefault 阻止浏览器默认行为。
|
||||
*
|
||||
* 生命周期:onMounted 注册、onBeforeUnmount 卸载,组件销毁后自动解绑。
|
||||
*/
|
||||
export function useHotkeys(shortcuts) {
|
||||
function onKeydown(e) {
|
||||
for (const s of shortcuts) {
|
||||
if (!matches(e, s)) continue
|
||||
if (s.ignoreWhenTyping !== false && isTypingTarget(e)) continue
|
||||
e.preventDefault()
|
||||
s.handler(e)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => window.addEventListener('keydown', onKeydown))
|
||||
onBeforeUnmount(() => window.removeEventListener('keydown', onKeydown))
|
||||
}
|
||||
Reference in new issue
Block a user