Skip to content

createSharedKeyboardCenter

创建共享的键盘事件中心,基于单例模式,只在第一次使用时添加键盘监听事件。

前置依赖

依赖参数

参数名类型说明
deps.addEventListenerWindow['addEventListener']添加事件监听函数
deps.removeEventListenerWindow['removeEventListener']移除事件监听函数
deps.logConsole['log']日志输出函数
deps.errorConsole['error']错误日志函数
deps.warnConsole['warn']警告日志函数

环境要求

  • 浏览器环境: 需要 Window 对象的 addEventListenerremoveEventListener 方法
  • 控制台对象: 需要 console 对象
typescript
const deps = {
  addEventListener: window.addEventListener,
  removeEventListener: window.removeEventListener,
  log: console.log,
  error: console.error,
  warn: console.warn
}

函数签名

typescript
function createSharedKeyboardCenter(
  deps: KeyboardCenterDeps
): KeyboardCenter

interface KeyboardCenterDeps {
  addEventListener: Window['addEventListener']
  removeEventListener: Window['removeEventListener']
  log: Console['log']
  error: Console['error']
  warn: Console['warn']
}

interface KeyboardCenter {
  subscribe(listener: KeyboardEventListener): () => void
  unsubscribe(listener: KeyboardEventListener): void
  getListenerCount(): number
  isInitialized(): boolean
}

type KeyboardEventListener = (event: KeyboardEvent) => void

参数

参数名类型必填说明
depsKeyboardCenterDeps依赖注入对象

返回值

类型说明
KeyboardCenter键盘事件中心实例(单例)

KeyboardCenter

方法名类型说明
subscribe(listener: KeyboardEventListener) => () => void订阅键盘事件,返回取消订阅函数
unsubscribe(listener: KeyboardEventListener) => void取消订阅键盘事件
getListenerCount() => number获取当前订阅者数量
isInitialized() => boolean检查是否已添加全局键盘监听

工作原理

  1. 单例模式:全局共享一个键盘事件中心实例,多次调用 createSharedKeyboardCenter 返回同一个实例
  2. 懒加载:只在第一次调用 subscribe() 时添加全局的 keydownkeyup 监听
  3. 订阅机制:支持多个订阅者,每个订阅者都会收到所有键盘事件
  4. 持久监听:即使移除所有订阅者,全局键盘监听仍然保持,不会主动移除
  5. 依赖注入:所有环境依赖通过参数传入,不直接使用全局对象

使用示例

基础使用

typescript
import { createSharedKeyboardCenter } from 'zcw-shared/functions/dom/createSharedKeyboardCenter'

// 创建键盘事件中心(单例)
const center = createSharedKeyboardCenter({
  addEventListener: window.addEventListener.bind(window),
  removeEventListener: window.removeEventListener.bind(window),
  log: console.log,
  error: console.error,
  warn: console.warn
})

// 订阅键盘事件
const unsubscribe = center.subscribe((event) => {
  console.log('按键:', event.key)
})

// 取消订阅
unsubscribe()

多个订阅者

typescript
import { createSharedKeyboardCenter } from 'zcw-shared/functions/dom/createSharedKeyboardCenter'

const center = createSharedKeyboardCenter({
  addEventListener: window.addEventListener,
  removeEventListener: window.removeEventListener,
  log: console.log,
  error: console.error,
  warn: console.warn
})

// 订阅者 1
const unsubscribe1 = center.subscribe((event) => {
  console.log('订阅者 1 收到:', event.key)
})

// 订阅者 2
const unsubscribe2 = center.subscribe((event) => {
  console.log('订阅者 2 收到:', event.key)
})

// 取消订阅者 1
unsubscribe1()

// 订阅者 2 仍然可以接收到键盘事件

在 Vue 组件中使用

typescript
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue'
import { createSharedKeyboardCenter } from 'zcw-shared/functions/dom/createSharedKeyboardCenter'

const center = createSharedKeyboardCenter({
  addEventListener: window.addEventListener,
  removeEventListener: window.removeEventListener,
  log: console.log,
  error: console.error,
  warn: console.warn
})

const keys: string[] = []

const handleKeyPress = (event: KeyboardEvent) => {
  keys.push(event.key)
  console.log('当前按键:', event.key)
}

onMounted(() => {
  center.subscribe(handleKeyPress)
})

onUnmounted(() => {
  center.unsubscribe(handleKeyPress)
})
</script>

快捷键监听

typescript
import { createSharedKeyboardCenter } from 'zcw-shared/functions/dom/createSharedKeyboardCenter'

const center = createSharedKeyboardCenter({
  addEventListener: window.addEventListener,
  removeEventListener: window.removeEventListener,
  log: console.log,
  error: console.error,
  warn: console.warn
})

center.subscribe((event) => {
  // 监听 Ctrl+S 或 Cmd+S(保存)
  if ((event.key === 's' && event.ctrlKey) || (event.key === 's' && event.metaKey)) {
    event.preventDefault()
    console.log('保存文件')
  }
  
  // 监听 Escape 键
  if (event.key === 'Escape') {
    console.log('取消操作')
  }
})

注意事项

  1. 单例特性:无论调用多少次 createSharedKeyboardCenter,都会返回同一个实例
  2. 持久监听:全局键盘监听会在添加后一直保持,即使移除所有订阅者也不会主动移除
  3. 性能优化:只有一个全局键盘监听器,不会因为多个订阅者而添加多个监听器
  4. 被动监听:事件监听使用 passive: true 选项,提升滚动性能
  5. 错误处理:监听器执行错误不会影响其他订阅者