Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Коли варто створювати власну директиву у Vue і як вона влаштована?

Власні директиви - для повторного використання низькорівневої роботи з DOM на звичайних елементах: фокус, перехоплення кліків поза елементом, підказки, виділення тексту, ліниве завантаження.

У <script setup> будь-яка змінна з назвою vЩось стає директивою v-щось:

<script setup>
const vFocus = {
  mounted: (el) => el.focus(),
};
</script>

<template>
  <input v-focus>
</template>

Повний набір хуків (усі необов'язкові):

const vClickOutside = {
  mounted(el, binding) {
    el._onClick = (event) => {
      if (!el.contains(event.target)) binding.value(event);
    };
    document.addEventListener('click', el._onClick);
  },
  unmounted(el) {
    document.removeEventListener('click', el._onClick);
  },
};
<div v-click-outside="closeMenu">...</div>

Хуки: created, beforeMount, mounted, beforeUpdate, updated, beforeUnmount, unmounted. Аргумент binding містить value, oldValue, arg (v-tooltip:top → 'top') і modifiers (v-tooltip.delay → { delay: true }).

Скорочена форма - функція замість об'єкта: викликається в mounted і updated.

Глобальна реєстрація - app.directive('focus', vFocus).

Коли директива - правильний вибір, а коли ні:

  • так: логіка прив'язана до конкретного DOM-елемента й не має власного шаблону чи складного стану;
  • ні - краще компонент: є розмітка (підказка з вмістом, випадне меню);
  • ні - краще composable: логіка зі станом, яку зручно використати в setup (useClickOutside(target, handler), useIntersectionObserver). Composable краще типізується й тестується;
  • ні - краще вбудовані директиви: документація радить декларативні v-bind, v-show там, де можливо, - вони ефективніші й дружні до SSR.

Пастки:

  • на компонентах директиви не рекомендовані: застосовуються до кореневого елемента, а на компоненті з кількома коренями ігноруються з попередженням (на відміну від атрибутів, їх не передати через $attrs);
  • аргументи хуків - лише для читання, крім el. Спільні дані між хуками - через el.dataset чи WeakMap, а не довільні властивості на елементі (як el._onClick у прикладі - працює, але це компроміс);
  • прибирання в unmounted обов'язкове для глобальних слухачів і спостерігачів;
  • SSR: хуки директив на сервері не викликаються (крім getSSRProps для атрибутів).

Докладніше в документації: Власні директиви

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання