Директивы во Vue.js — это специальные атрибуты, которые добавляют
поведение к DOM-элементам. Помимо встроенных директив
(v-if, v-for, v-model и др.), Vue
позволяет создавать собственные пользовательские директивы для
повторного использования логики взаимодействия с DOM.
Пользовательская директива регистрируется глобально или локально.
Глобальная регистрация:
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
app.directive('focus', {
mounted(el) {
el.focus();
}
});
app.mount('#app');
Здесь создается директива v-focus, которая устанавливает
фокус на элемент при его монтировании в DOM.
Локальная регистрация:
export default {
directives: {
highlight: {
beforeMount(el, binding) {
el.style.backgroundColor = binding.value || 'yellow';
}
}
}
};
Локальная директива доступна только внутри конкретного компонента.
Пользовательские директивы во Vue имеют набор хуков, аналогичный жизненному циклу компонентов:
beforeMount(el, binding, vnode, prevVnode)
– вызывается до монтирования элемента.mounted(el, binding, vnode, prevVnode)
– вызывается после монтирования элемента.beforeUpdate(el, binding, vnode, prevVnode)
– вызывается перед обновлением VNode.updated(el, binding, vnode, prevVnode)
– вызывается после обновления VNode.beforeUnmount(el, binding, vnode, prevVnode)
– вызывается перед удалением элемента.unmounted(el, binding, vnode, prevVnode)
– вызывается после удаления элемента.Параметр binding содержит важные свойства:
binding.value — значение, переданное
директиве.binding.oldValue — предыдущее
значение.binding.arg — аргумент директивы
(например, в v-my-directive:arg будет
arg).binding.modifiers — объект
модификаторов, например { lazy: true } для
v-my-directive.lazy.Изменение стиля элемента:
app.directive('color', {
beforeMount(el, binding) {
el.style.color = binding.value || 'red';
},
updated(el, binding) {
el.style.color = binding.value || 'red';
}
});
Использование в шаблоне:
<p v-color="'blue'">Текст с синим цветом</p>
Динамическая обработка событий:
app.directive('click-outside', {
mounted(el, binding) {
el.__clickOutsideHandler__ = (event) => {
if (!el.contains(event.target)) {
binding.value(event);
}
};
document.addEventListener('click', el.__clickOutsideHandler__);
},
unmounted(el) {
document.removeEventListener('click', el.__clickOutsideHandler__);
delete el.__clickOutsideHandler__;
}
});
Применение:
<div v-click-outside="handleClickOutside">Содержимое</div>
В этом примере директива реагирует на клики за пределами элемента,
вызывая функцию handleClickOutside.
Директивы могут использовать модификаторы для расширения функционала:
app.directive('scroll', {
mounted(el, binding) {
const beh * avior = binding.modifiers.smooth ? 'smooth' : 'auto';
el.addEventListener('scroll', () => {
console.log('Скролл с поведением', behavior);
});
}
});
Использование:
<div v-scroll.smooth>Прокручиваемый элемент</div>
Аргументы позволяют передавать дополнительную информацию:
app.directive('style', {
mounted(el, binding) {
el.style[binding.arg] = binding.value;
}
});
Пример в шаблоне:
<p v-style:background="'lightblue'">Фон элемента изменен</p>
unmounted, чтобы избежать утечек памяти.app.directive('my-directive', {
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 в Vue.js.