# Переименованы хуки пользовательских директив
кардинальное изменение
# Обзор
Были переименованы функции хуков директив, чтобы лучше соответствовать жизненному циклу компонента.
Кроме того, строка expression
больше не передаётся как часть объекта binding
.
# Синтаксис в 2.x
Во Vue 2 пользовательские директивы создавались с использованием хуков, указанных ниже, для обозначения жизненного цикла элемента, все они являлись опциональными:
- bind - вызывается при привязке директивы к элементу. Вызывается только один раз.
- inserted - вызывается после того, как элемент вставлен в родительский DOM.
- update - вызывается при обновлениях элемента, но дочерние ещё не будут обновлены.
- componentUpdated - вызывается после обновления компонента и его потомков.
- unbind - вызывается после удаления директивы. Также вызывается только один раз.
Пример:
<p v-highlight="'yellow'">Выделить этот текст ярко-жёлтым</p>
Vue.directive('highlight', {
bind(el, binding, vnode) {
el.style.background = binding.value
}
})
2
3
4
5
Здесь, при начальной инициализации для этого элемента, директива устанавливает стиль, передавая значение, которое может обновляться до различных значений в приложении.
# Синтаксис в 3.x
Во Vue 3 теперь создан более согласованный API для пользовательских директив. Как можно увидеть, раньше он сильнее отличался от хуков жизненного цикла компонента, даже если привязывались к похожим событиям. Теперь они также унифицированы:
- created - Новый! Вызывается перед применением атрибутов к элементу или слушателей событий.
- bind → beforeMount
- inserted → mounted
- beforeUpdate: Новый! Вызывается перед обновлением самого элемента, подобно хуку жизненного цикла компонента.
- update → Удалён! Слишком много сходств с
updated
, поэтому он избыточен. Вместо него используйтеupdated
. - componentUpdated → updated
- beforeUnmount: Новый! Подобно хуку жизненного цикла компонента, будет вызываться перед тем, как элемент будет размонтирован.
- unbind -> unmounted
Финальное API выглядит так:
const MyDirective = {
created(el, binding, vnode, prevVnode) {}, // новый
beforeMount() {},
mounted() {},
beforeUpdate() {}, // новый
updated() {},
beforeUnmount() {}, // новый
unmounted() {}
}
2
3
4
5
6
7
8
9
Используя обновлённое API, предыдущий пример теперь будет выглядеть так:
<p v-highlight="'yellow'">Выделить этот текст ярко-жёлтым</p>
const app = Vue.createApp({})
app.directive('highlight', {
beforeMount(el, binding, vnode) {
el.style.background = binding.value
}
})
2
3
4
5
6
7
Теперь, когда хуки жизненного цикла пользовательских директив зеркально отражают хуки компонентов стало проще понимать когда их применять и проще запоминать!
# Крайний случай: Доступ к экземпляру компонента
Обычно рекомендуется сохранять директивы независимыми от экземпляра компонента, в котором они используются. Доступ к экземпляру внутри пользовательской директивы часто является признаком того, что директива скорее сама должна быть компонентом. Но бывают ситуации, когда это имеет смысл.
Во Vue 2 экземпляр компонента можно получить через аргумент vnode
:
bind(el, binding, vnode) {
const vm = vnode.context
}
2
3
Во Vue 3 этот экземпляр теперь является частью binding
:
mounted(el, binding, vnode) {
const vm = binding.instance
}
2
3
ВНИМАНИЕ
С появлением фрагментов компоненты теперь могут иметь больше одного корневого элемента. Если применить пользовательскую директиву к компоненту с несколькими корневыми элементами, то она будет проигнорирована и выведено предупреждение.