Приведи пример использования кастомной директивы
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Приведи пример использования кастомной директивы
Кастомные директивы — это один из мощных инструментов в современных фреймворках (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 во множестве компонентов.