20260911173133
This commit is contained in:
1 parent
3838ed74b1
commit
f3ad727f1c
60 files changed
+4971
-6621
No files matched your search
@@ -1,4 +1,4 @@
|
||||
import { onBeforeUnmount, onMounted } from 'vue'
|
||||
import { onActivated, onBeforeUnmount, onDeactivated, onMounted } from 'vue'
|
||||
|
||||
// 输入态判断:焦点在 input / textarea / 可编辑区域
|
||||
function isTypingTarget(e) {
|
||||
@@ -6,9 +6,21 @@ function isTypingTarget(e) {
|
||||
return !!el && (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.isContentEditable)
|
||||
}
|
||||
|
||||
/**
|
||||
* 主键匹配:优先用 e.key;中文输入法组合中(拼音尚未上屏)时 e.key 为
|
||||
* 'Process' / 'Unidentified',此时退回物理键位 e.code('KeyS' → 's')兜底。
|
||||
* 否则「输入法激活时按 Ctrl+S」会概率性不匹配,表现为快捷键时灵时不灵。
|
||||
*/
|
||||
function keyMatches(e, key) {
|
||||
const target = String(key).toLowerCase()
|
||||
if (String(e.key || '').toLowerCase() === target) return true
|
||||
const code = String(e.code || '')
|
||||
return code.startsWith('Key') && code.slice(3).toLowerCase() === target
|
||||
}
|
||||
|
||||
// 快捷键匹配:精确匹配(未声明的修饰符按下则不匹配)
|
||||
function matches(e, s) {
|
||||
if (e.key.toLowerCase() !== String(s.key).toLowerCase()) return false
|
||||
if (!keyMatches(e, s.key)) return false
|
||||
// 主修饰键:声明了 mod / ctrl / meta 中任一 → 要求 Ctrl 或 Meta 按下
|
||||
const needsMod = s.mod === true || s.ctrl === true || s.meta === true
|
||||
const modPressed = e.ctrlKey || e.metaKey
|
||||
@@ -38,7 +50,12 @@ function matches(e, s) {
|
||||
* 组合保存类快捷键(如 Ctrl+S)通常传 false,保证输入时也能保存。
|
||||
* handler(e) —— 触发回调,默认已 preventDefault 阻止浏览器默认行为。
|
||||
*
|
||||
* 生命周期:onMounted 注册、onBeforeUnmount 卸载,组件销毁后自动解绑。
|
||||
* 生命周期:
|
||||
* - 监听注册在 window 的**捕获阶段**:后代元素上的 @keydown.stop / stopPropagation
|
||||
* 只阻断冒泡,捕获阶段仍能收到,避免个别控件(如结构树重命名输入框)内快捷键失效;
|
||||
* - onMounted 注册、onBeforeUnmount 卸载;
|
||||
* - keep-alive 缓存的页面切走后实例仍存活,故 onDeactivated 解绑、onActivated 重新绑定:
|
||||
* 否则同时打开的多个页签(如模块管理 / 菜单管理)会一起响应同一次 Ctrl+S 而互相干扰。
|
||||
*/
|
||||
export function useHotkeys(shortcuts) {
|
||||
function onKeydown(e) {
|
||||
@@ -51,6 +68,21 @@ export function useHotkeys(shortcuts) {
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => window.addEventListener('keydown', onKeydown))
|
||||
onBeforeUnmount(() => window.removeEventListener('keydown', onKeydown))
|
||||
let bound = false
|
||||
function bind() {
|
||||
if (bound) return
|
||||
window.addEventListener('keydown', onKeydown, true)
|
||||
bound = true
|
||||
}
|
||||
function unbind() {
|
||||
if (!bound) return
|
||||
window.removeEventListener('keydown', onKeydown, true)
|
||||
bound = false
|
||||
}
|
||||
|
||||
onMounted(bind)
|
||||
// keep-alive 内首次挂载后也会触发 activated,bind 幂等无需额外判断
|
||||
onActivated(bind)
|
||||
onDeactivated(unbind)
|
||||
onBeforeUnmount(unbind)
|
||||
}
|
||||
Reference in new issue
Block a user