Користувацькі директиви у Vue.js
Що таке Користувацькі Директиви?
Користувацькі директиви розширюють синтаксис шаблонів Vue логікою повторного використання для маніпуляції DOM. Хоча компоненти є основними будівельними блоками, директиви корисні для низькорівневого доступу до DOM, який не підходить для моделі компонентів.
Основна Директива
vue
<!-- Автофокус на елементі вводу при монтуванні -->
<script setup>
const vFocus = {
mounted(el: HTMLElement) {
el.focus()
}
}
</script>
<template>
<input v-focus />
</template>Хуки Життєвого Циклу Директиви
typescript
const myDirective = {
// Викликається перед монтуванням елемента
created(el, binding, vnode) {},
// Викликається, коли елемент вставлений у DOM
mounted(el, binding, vnode) {},
// Викликається перед оновленням батьківського компонента
beforeUpdate(el, binding, vnode, prevVnode) {},
// Викликається після оновлення батьківського компонента
updated(el, binding, vnode, prevVnode) {},
// Викликається перед демонтажем елемента
beforeUnmount(el, binding, vnode) {},
// Викликається, коли елемент демонтується
unmounted(el, binding, vnode) {},
}Об'єкт binding
vue
<div v-my-directive:arg.mod1.mod2="value">
<!-- binding містить: -->
<!-- {
value: value, // Поточне значення
oldValue: ..., // Попереднє значення (в updated)
arg: 'arg', // Аргумент після двокрапки
modifiers: { mod1: true, mod2: true },
instance: ..., // Екземпляр компонента
dir: ..., // Визначення директиви
} -->Практичні Приклади
Клік Ззовні
typescript
// directives/clickOutside.ts
export const vClickOutside = {
mounted(el: HTMLElement, binding: { value: () => void }) {
el._clickOutsideHandler = (event: MouseEvent) => {
if (!el.contains(event.target as Node)) {
binding.value()
}
}
document.addEventListener('click', el._clickOutsideHandler)
},
unmounted(el: HTMLElement) {
document.removeEventListener('click', el._clickOutsideHandler)
},
}vue
<template>
<div v-click-outside="closeDropdown" class="dropdown">
<!-- Вміст випадаючого меню -->
</div>
</template>Спостерігач Перетворення (Ліниве Завантаження)
typescript
export const vLazyLoad = {
mounted(el: HTMLImageElement, binding: { value: string }) {
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
el.src = binding.value
observer.disconnect()
}
})
observer.observe(el)
},
}vue
<img v-lazy-load="imageUrl" />Підказка
typescript
export const vTooltip = {
mounted(el: HTMLElement, binding: { value: string }) {
el.title = binding.value
el.style.cursor = 'help'
},
updated(el: HTMLElement, binding: { value: string }) {
el.title = binding.value
},
}Глобальна Реєстрація
typescript
// main.ts
import { createApp } from 'vue'
import { vClickOutside } from './directives/clickOutside'
const app = createApp(App)
app.directive('click-outside', vClickOutside)
app.mount('#app')Коли Використовувати Директиви vs Композиції
| Використовуйте Директиви | Використовуйте Композиції |
|---|---|
| Пряма маніпуляція DOM | Реактивна логіка стану |
| Інтеграція сторонніх бібліотек | Отримання даних |
| Низькорівневе оброблення подій | Спільна бізнес-логіка |
| Поведінка, специфічна для елемента | Логіка, незалежна від компонентів |
Важливо:
Користувацькі директиви призначені для низькорівневої маніпуляції DOM, яка не підходить для компонентів або композицій. Загальні випадки використання включають виявлення кліків ззовні, спостерігач перетворення, підказки та управління фокусом. Для всього іншого надавайте перевагу композиціям (функціям, що повторно використовуються), оскільки вони більш гнучкі та тестовані.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.