Директивы Vue: как создавать и регистрировать кастомные директивы

Директивы — это конструкты языка программирования в экосистеме Vue, которые указывают компилятору и рантайму, как обрабатывать конкретный DOM-элемент при выполнении приложения. С их помощью можно привязывать обработчики событий, изменять стиль, управлять фокусом и реализовать другие повторно используемые низкоуровневые сценарии работы с элементами.
Структура директив Vue
Директивы в Vue помечаются префиксом v- — это сигнал для компилятора Vue, что атрибут не обычный HTML, а директива, и её нужно обработать.
Простой пример с использованием v-show для отображения h2:
Hello Vue
Vue предоставляет ряд встроенных директив: v-bind, v-if, v-on и другие. Они покрывают задачи привязки данных, условного рендеринга и обработки событий.
Определение кастомных директив в Vue
Кастомные директивы позволяют вынести повторяющуюся логику работы с DOM в переиспользуемые блоки. Процесс создания обычно состоит из двух шагов: регистрация (локальная или глобальная) и определение поведения через хуки жизненного цикла.
Регистрация кастомных директив
Директиву можно зарегистрировать локально в компоненте или глобально для всего приложения. Чаще применяют глобальную регистрацию, когда директива должна быть доступна в разных местах приложения. Локальная регистрация уместна для специфичных компонентов.
Пример локальной регистрации директивы v-changecolor в компоненте:
Learn about custom directives
Аналогично можно зарегистрировать директиву глобально в main.js:
// main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.directive('changecolor', {
mounted(el, binding, vnode) {
// глобальная логика при монтировании
}
})
app.mount('#app')Глобальная регистрация удобна для общих утилит. Локальная — для узкоспецифичных задач.
Определение поведения директивы
Директивы — это объект с хуками жизненного цикла или короткая функция (если нужны только mounted/updated). Хуки получают DOM-элемент (el), объект binding и виртуальный узел (vnode).
Пример объекта с хуками mounted и updated:
const directiveObject = {
mounted(el, binding, vnode) {
// выполнится при монтировании
},
updated(el, binding, vnode) {
// выполнится при обновлении
}
}
app.directive('changecolor', directiveObject)Если поведение одинаково для mounted и updated, можно записать директиву как функцию:
app.directive('changecolor', (el, binding, vnode) => {
const message = 'Are you sure you want to change the color?'
el.addEventListener('click', () => {
if (confirm(message)) {
el.style.color = binding.value || "#" + Math.random().toString().slice(2, 8);
}
})
})Здесь el — реальный DOM-элемент, binding.value — значение, переданное директиве (например, ‘red’), vnode содержит метаданные виртуального узла.
Пример тестового компонента
Hello Vue
Learn custom directives
Can't Wait to Get Started {{ name }}
При клике на элементы: если значение директивы задано (‘red’), тот элемент останется красным. Если значение не задано — цвет выбирается случайно после подтверждения.
Когда стоит и когда не стоит использовать директивы
Важно: директивы хороши для низкоуровневых манипуляций DOM и поведения, которое трудно выразить через компонент или composition API. Но есть ограничения.
Используйте директивы когда:
- Нужен прямой доступ к DOM (фокус, размеры, сторонние библиотеки).
- Логика применима к множеству элементов по приложению.
- Нельзя легко выразить поведение через шаблон/компонент.
Не используйте директивы когда:
- Логика связана с состоянием приложения и должна быть тестируема на уровне компонента.
- Поведение проще вынести в компонент-обёртку или composable.
- Нужно управлять layout или рендерингом — лучше компонент.
Важно: директивы — это инструмент; злоупотребление ими усложняет тестирование и делает логику менее декларативной.
Альтернативы директивам
- Компоненты-обёртки — инкапсулируют поведение и управляют рендером.
- Composition API (composables) — для повторного использования бизнес-логики без прямого обращения к DOM.
- Сторонние утилиты и библиотеки для конкретных задач (например, менеджеры фокуса).
Выбор зависит от уровня абстракции и тестируемости: если нужна декларативность и переиспользуемость с явным API — компонент или composable предпочтительнее.
Мини‑методология: как правильно создать директиву (шаблон действий)
- Оцените проблему: нужна ли прямая работа с DOM?
- Решите область действия: глобальная или локальная регистрация?
- Определите хуки: mounted, updated, unmounted и т.д.
- Реализуйте и изолируйте побочные эффекты (очищайте обработчики в unmounted).
- Напишите unit/интеграционные тесты для поведения и сценариев кликов/фокуса.
- Документируйте API директивы: ожидаемые значения binding, аргументы и модификаторы.
Контрольные списки по ролям
Разработчик:
- Проверил область действия (локальная/глобальная).
- Добавил очистку обработчиков в unmounted.
- Документировал binding.value и возможные аргументы.
Архитектор:
- Убедился, что директива не дублирует функционал компонента.
- Одобрил глобальную регистрацию только для действительно общих функций.
Ревьюер PR:
- Проверил тесты и сценарии отказа.
- Убедился, что директива не изменяет глобальное состояние приложения неожиданно.
Критерии приёмки
- Директива корректно регистрируется и применяется к элементам.
- Поведение соответствует спецификации (binding.value работает, обработчики размещены).
- При размонтировании нет утечек памяти (обработчики удаляются).
- Наличие документации и примеров использования.
Тестовые случаи и критерии приёмки
- Кликовый сценарий: элемент с v-changecolor изменяет цвет при подтверждении.
- Значение binding.value имеет приоритет перед случайным цветом.
- Поведение повторяется после обновления компонента (updated hook).
- После unmounted обработчик удалён и клики не вызывают ошибок.
Риски и рекомендации по безопасности
- Не используйте confirm/alert в продакшн-коде без UX-подтверждения — они блокируют поток.
- Если директива взаимодействует с внешними библиотеками, следите за утечками событий и XSS при работе со строками.
- Избегайте манипуляций innerHTML без санитизации.
Совместимость и миграция
Директивы в Vue 3 сохраняют знакомые API, но при миграции с Vue 2 стоит проверить различия в жизненных циклах и API рендера. Vue 3.x и выше активно развиваются; перед применением новых возможностей сверяйтесь с официальным changelog.
Быстрый справочник (cheat sheet)
- Регистрация глобально: app.directive(name, definition)
- Регистрация локально: экспорт объекта директивы в компоненте
- Хуки директив: created, beforeMount, mounted, beforeUpdate, updated, beforeUnmount, unmounted
- Короткая форма: app.directive(name, (el, binding) => { / mounted+updated / })
Однострочный глоссарий
- binding — объект с { value, oldValue, arg, modifiers } для доступа к параметрам директивы.
- vnode — виртуальный DOM-узел Vue для элемента.
- mounted — хук, вызываемый при добавлении элемента в DOM.
Заключение
Кастомные директивы дают мощный инструмент для работы с DOM и подходят для задач, где компоненты и composables неудобны или избыточны. Придерживайтесь практик: чистка эффектов, документирование API и выбор правильной области видимости (локально/глобально). Тщательно тестируйте и по возможности отдавайте предпочтение декларативным решениям, если они упрощают поддержку.
Краткая заметка: Vue 3.3 принес улучшения для расширяемости — ознакомьтесь с официальным changelog, чтобы использовать последние рекомендации.
Сводка:
- Директивы — для низкоуровневых манипуляций с DOM.
- Регистрация: локально или глобально.
- Хуки жизненного цикла определяют поведение.
- Тесты, документация и очистка обработчиков — обязательны.
Похожие материалы
Отключить автозапуск видео в Facebook (Android/iOS)
Скопировать TWRP‑резервные копии на ПК
FTP в Linux: подключение, команды и безопасность
Как сохранить GIF из Twitter
Запуск Windows Mobile 6.5 на ПК