Кастомные директивы
↑ 4.1 Vue 3: основы, компоненты, Composition API · ← Предыдущая · → Следующая
Зачем это на собесе
Когда нужна директива и как она работает с DOM в хуках жизненного цикла.
Объяснение
Директива инкапсулирует низкоуровневый доступ к DOM (фокус, drag, клик вне, tooltip). Логику компонентов и состояния реализуйте composables/компонентами.
// Локальная в <script setup>: переменная с префиксом v
const vFocus = { mounted: (el: HTMLElement) => el.focus() };
// Глобальная
app.directive("click-outside", {
mounted(el, binding) {
el._handler = (e: MouseEvent) => { if (!el.contains(e.target as Node)) binding.value(e); };
document.addEventListener("click", el._handler);
},
unmounted(el) { document.removeEventListener("click", el._handler); },
});<input v-focus />
<div v-click-outside="close" />
<div v-tooltip.top="'Подсказка'" /> <!-- binding.arg / binding.modifiers -->Хуки: created, beforeMount, mounted, beforeUpdate, updated, beforeUnmount, unmounted. Аргументы: el, binding (value, oldValue, arg, modifiers, instance), vnode. Сокращённая форма: функция = mounted + updated.
Когда использовать: фокус, click-outside, lazy-load изображений, ресайз-наблюдатели, права доступа (v-can), маски ввода.
Альтернатива: composable с useEventListener/onClickOutside из VueUse и template ref.
Нюансы и подводные камни
- Всегда снимайте слушатели в
unmounted. - Директивы не работают на компонентах с несколькими корнями (применяются к корню,
inheritAttrs). - В SSR нет DOM: используйте
getSSRProps/защиту. - Не храните состояние в
elбез необходимости — лучшеWeakMap.
Практика
- Напишите
v-click-outsideс очисткой. - Реализуйте директиву
v-can="'orders:edit'", скрывающую элемент без права. - Сравните с
onClickOutsideиз VueUse.
Вопросы с ответами
Когда нужна кастомная директива?
Когда требуется прямая работа с DOM, повторяемая для разных элементов.
Какие хуки есть у директивы?
created,beforeMount,mounted,beforeUpdate,updated,beforeUnmount,unmounted.