Создаем универсальный хук для клавиатурных сокращений в Vue 3

от автора

в
Время чтения: 3 мин.

В современной веб-разработке удобство пользователя — это главный приоритет. Сегодня мы создадим мощный и гибкий composable-хук useKeyBinding для Vue 3, который позволит легко добавлять клавиатурные сокращения к input-полям вашего приложения.

Зачем нужен хук useKeyBinding?

Клавиатурные сокращения — это не просто фича, а must-have для:

  • Форм с частым вводом данных
  • Админ-панелей и CRM-систем
  • Приложений, где важна скорость работы
  • Редакторов и инструментов для профессионалов

Наш хук будет:

  • Поддерживать любые комбинации клавиш
  • Работать только с нужным input-элементом
  • Автоматически очищать listeners
  • Быть полностью типизированным

Создаем основу хука

Создадим файл useKeyBinding.ts:

import { onMounted, onUnmounted } from 'vue'
import type { Ref } from 'vue'

type KeyBindingMap = {
  [keyCombo: string]: (e: KeyboardEvent) => void
}

export function useKeyBinding(inputRef: Ref<HTMLInputElement | null>, bindings: KeyBindingMap) {
  // Обработчик событий клавиатуры
  const handler = (e: KeyboardEvent) => {
    // Работаем только с нашим input-элементом
    if (e.target !== inputRef.value) return

    // Формируем комбинацию клавиш
    const keyCombo = [
      e.ctrlKey && 'Ctrl',
      e.metaKey && 'Meta',
      e.shiftKey && 'Shift',
      e.altKey && 'Alt',
      e.key,
    ]
      .filter(Boolean)
      .join('+')

    // Вызываем обработчик если он есть
    bindings[keyCombo]?.(e)
  }

  // Добавляем и удаляем listener
  onMounted(() => inputRef.value?.addEventListener('keydown', handler))
  onUnmounted(() => inputRef.value?.removeEventListener('keydown', handler))
}

Примеры использования

1. Базовое использование

Добавим обработчики для текстового поля:

<script setup lang="ts">
import { ref } from 'vue'
import { useKeyBinding } from './useKeyBinding'

const searchInput = ref<HTMLInputElement | null>(null)

useKeyBinding(searchInput, {
  'Enter': () => console.log('Search submitted!'),
  'Escape': () => {
    if (searchInput.value) searchInput.value.value = ''
  },
  'Ctrl+k': (e) => {
    e.preventDefault()
    console.log('Quick search activated')
  }
})
</script>

<template>
  <input ref="searchInput" placeholder="Поиск..." />
</template>

2. Форма с горячими клавишами

Реализуем форму с быстрыми действиями:

<script setup lang="ts">
const formInput = ref<HTMLInputElement | null>(null)
const draft = ref('')

useKeyBinding(formInput, {
  'Ctrl+Enter': () => submitForm(),
  'Shift+ArrowUp': () => increaseValue(),
  'Alt+s': () => saveDraft(),
})

function submitForm() {
  console.log('Форма отправлена:', draft.value)
}

function saveDraft() {
  console.log('Черновик сохранен:', draft.value)
}
</script>

<template>
  <textarea ref="formInput" v-model="draft"></textarea>
</template>

3. Комбинации для редактора

Создадим простой текстовый редактор:

<script setup lang="ts">
const editor = ref<HTMLInputElement | null>(null)
const text = ref('')

useKeyBinding(editor, {
  'Ctrl+b': () => wrapSelection('**', '**'),
  'Ctrl+i': () => wrapSelection('_', '_'),
  'Ctrl+Shift+l': () => insertLink(),
})

function wrapSelection(prefix: string, suffix: string) {
  // Логика обработки выделенного текста
}

function insertLink() {
  // Вставка ссылки
}
</script>

Продвинутые сценарии

Обработка модификаторов

Хук автоматически обрабатывает все популярные модификаторы:

useKeyBinding(inputRef, {
  'Ctrl+Alt+Delete': () => resetSystem(), // Полный контроль!
  'Meta+ArrowRight': () => nextTab(), // Для Mac пользователей
})

Динамические binding

Вы можете динамически изменять bindings:

<script setup lang="ts">
const bindings = reactive<KeyBindingMap>({
  'Enter': submitForm
})

// Позже можно изменить
bindings['Enter'] = alternateSubmit
</script>

Лучшие практики

  1. Используйте preventDefault когда нужно отменить стандартное поведение:
'Ctrl+s': (e) => {
  e.preventDefault()
  saveDocument()
}
  1. Документируйте сочетания клавиш для пользователей:
<template>
  <input ref="input" />
  <div class="hints">
    Ctrl+Enter: Отправить • Esc: Очистить
  </div>
</template>
  1. Учитывайте платформу — на Mac чаще используют Meta (Cmd), а на Windows — Ctrl.

Заключение

Наш хук useKeyBinding предоставляет простой и элегантный способ добавить клавиатурные сокращения в ваше Vue-приложение. Он:

  • Уменьшает количество шаблонного кода
  • Улучшает UX для опытных пользователей
  • Легко интегрируется в любые компоненты
  • Полностью типобезопасен

Попробуйте внедрить этот хук в свой проект и вы сразу заметите, насколько удобнее станет работать с формами и интерактивными элементами!

Дополнительные идеи для развития:

  • Добавить глобальные hotkeys (не привязанные к input)
  • Реализовать систему плагинов для предустановленных binding-ов
  • Создать визуальный конструктор hotkeys
  • Добавить поддержку последовательностей клавиш (как в Vim)

Какие клавиатурные сокращения вы чаще всего используете в своих проектах? Делитесь идеями в комментариях!


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Сколько будет 9 + 10?