← Назад к вопросам

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

2.0 Middle🔥 191 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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

Кастомные директивы — это один из мощных инструментов в современных фреймворках (Vue, React через кастомные хуки, Angular). Директива позволяет инкапсулировать логику взаимодействия с DOM элементом и переиспользовать её в разных компонентах.

Что такое директива

Директива — это функция, которая автоматически вызывается при монтировании и размонтировании элемента, позволяя манипулировать DOM и добавлять поведение.

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

Пример 1: Директива v-focus (Vue 3)

Директива, которая автоматически устанавливает фокус на элемент при монтировании:

// main.js
const app = createApp({});

// Регистрируем глобальную директиву
app.directive('focus', {
  mounted(el) {
    el.focus();
  }
});

// Использование в компоненте
export default {
  template: `
    <input v-focus placeholder="Это поле получит фокус" />
  `
};

Пример 2: Директива v-click-outside

Директива, которая вызывает коллбэк, когда кликнули вне элемента:

app.directive('click-outside', {
  mounted(el, binding) {
    el.clickOutsideEvent = function(event) {
      if (!(el === event.target || el.contains(event.target))) {
        binding.value(event);
      }
    };
    document.addEventListener('click', el.clickOutsideEvent);
  },
  unmounted(el) {
    document.removeEventListener('click', el.clickOutsideEvent);
  }
});

// Использование
export default {
  data() {
    return {
      isOpen: false
    };
  },
  template: `
    <div v-click-outside="closeMenu" class="dropdown">
      <button @click="isOpen = !isOpen">Menu</button>
      <div v-if="isOpen" class="menu">
        <a href="#">Item 1</a>
        <a href="#">Item 2</a>
      </div>
    </div>
  `,
  methods: {
    closeMenu() {
      this.isOpen = false;
    }
  }
};

Пример 3: Директива v-lazy-load

Директива для ленивой загрузки изображений:

app.directive('lazy-load', {
  mounted(el, binding) {
    const imageUrl = binding.value;
    
    if ('IntersectionObserver' in window) {
      const observer = new IntersectionObserver((entries, obs) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            el.src = imageUrl;
            el.classList.add('loaded');
            obs.unobserve(el);
          }
        });
      });
      
      observer.observe(el);
    } else {
      el.src = imageUrl; // Fallback для старых браузеров
    }
  }
});

// Использование
export default {
  template: `
    <img v-lazy-load="'https://example.com/large-image.jpg'" alt="Lazy loaded" />
  `
};

Пример 4: Директива v-highlight

Директива, которая подсвечивает текст при наведении:

app.directive('highlight', {
  mounted(el, binding) {
    const color = binding.value || 'yellow';
    el.style.backgroundColor = color;
  },
  updated(el, binding) {
    const color = binding.value || 'yellow';
    el.style.backgroundColor = color;
  }
});

// Использование
export default {
  data() {
    return {
      highlightColor: 'yellow'
    };
  },
  template: `
    <div>
      <p v-highlight="highlightColor">Этот текст подсвечен</p>
      <button @click="highlightColor = 'lightblue'">Change color</button>
    </div>
  `
};

Кастомный хук в React (аналог директивы)

В React нет директив, но есть кастомные хуки, которые достигают аналогичного результата:

// useClickOutside.js
import { useEffect, useRef } from 'react';

function useClickOutside(callback) {
  const ref = useRef(null);

  useEffect(() => {
    function handleClickOutside(event) {
      if (ref.current && !ref.current.contains(event.target)) {
        callback();
      }
    }

    document.addEventListener('click', handleClickOutside);
    return () => document.removeEventListener('click', handleClickOutside);
  }, [callback]);

  return ref;
}

// Использование
function Dropdown() {
  const [isOpen, setIsOpen] = useState(false);
  const ref = useClickOutside(() => setIsOpen(false));

  return (
    <div ref={ref} className="dropdown">
      <button onClick={() => setIsOpen(!isOpen)}>Menu</button>
      {isOpen && (
        <div className="menu">
          <a href="#">Item 1</a>
          <a href="#">Item 2</a>
        </div>
      )}
    </div>
  );
}

Практический пример: Директива v-throttle

Директива, которая ограничивает количество вызовов события:

app.directive('throttle', {
  mounted(el, binding) {
    let timeout;
    const delay = binding.arg || 300; // Задержка в миллисекундах
    const callback = binding.value;

    el.addEventListener('click', function(event) {
      if (!timeout) {
        callback(event);
        timeout = setTimeout(() => {
          timeout = null;
        }, delay);
      }
    });
  }
});

// Использование
export default {
  template: `
    <button v-throttle:300="onSearch">Search</button>
  `,
  methods: {
    onSearch() {
      console.log('Search called (max once per 300ms)');
      // Выполни поиск
    }
  }
};

Когда использовать кастомные директивы

Подходит для:

  • Взаимодействия с DOM (фокус, ввод, медиа)
  • Повторяющейся логики, специфичной для элемента
  • Оборачивания сторонних библиотек (jQuery плагины, D3 и т.д.)
  • Сложной манипуляции DOM

НЕ подходит для:

  • Логики компонента (используй useState, computed)
  • Условного рендеринга (используй v-if, v-show)
  • Списков и итераций (используй v-for)

Жизненный цикл директивы (Vue 3)

app.directive('example', {
  created(el, binding, vnode, prevVnode) {
    // Вызывается перед монтированием
  },
  beforeMount(el, binding, vnode, prevVnode) {
    // Перед монтированием элемента
  },
  mounted(el, binding, vnode, prevVnode) {
    // После монтирования
  },
  beforeUpdate(el, binding, vnode, prevVnode) {
    // Перед обновлением компонента
  },
  updated(el, binding, vnode, prevVnode) {
    // После обновления
  },
  beforeUnmount(el, binding, vnode, prevVnode) {
    // Перед размонтированием
  },
  unmounted(el, binding, vnode, prevVnode) {
    // После размонтирования
  }
});

Итог

Кастомные директивы — это инструмент для инкапсуляции логики DOM в переиспользуемые блоки. Они особенно полезны для:

  • Фокусировки, валидации, маскирования входных данных
  • Обработки кликов снаружи элемента
  • Ленивой загрузки медиа
  • Интеграции с внешними библиотеками

Использование директив делает код более чистым и переиспользуемым, избегая дублирования логики DOM во множестве компонентов.