Кастомные директивы

↑ 4.1 Vue 3: основы, компоненты, Composition API · ← Предыдущая · → Следующая

Обязательно~3 мин чтенияУровень: middle

Зачем это на собесе

Когда нужна директива и как она работает с 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.

Практика

  1. Напишите v-click-outside с очисткой.
  2. Реализуйте директиву v-can="'orders:edit'", скрывающую элемент без права.
  3. Сравните с onClickOutside из VueUse.

Вопросы с ответами

Связанные темы