@ttbooking/vue-click-outside-directive
v1.1.0
Published
Директива для Vue, которая вызывает переданный callback при клике мышью за пределами элемента и его дочерних элементов.
Readme
vue-click-outside-directive
Директива для Vue, которая вызывает переданный callback при клике мышью за пределами элемента и его дочерних элементов.
Пакет подходит для типичных сценариев вроде закрытия dropdown, modal, popover, tooltip, context menu или другого UI, который должен скрываться при клике снаружи.
Что делает пакет
Директива навешивает обработчик mousedown на document.body.
При каждом клике она проверяет:
- кликнули ли непосредственно по элементу с директивой;
- кликнули ли по дочернему элементу;
- был ли клик по scrollbar;
- передан ли в директиву callback.
Если клик был снаружи элемента, директива вызывает переданную функцию:
<div v-click-outside="close">
Dropdown content
</div>Совместимость
Пакет рассчитан на совместимость с Vue 2 и Vue 3.
Поддерживаемые хуки директив:
| Vue | Setup hook | Cleanup hook |
| --- | --- | --- |
| Vue 2 | bind | unbind |
| Vue 3 | mounted | unmounted |
В текущей реализации callback берется из binding.value. Это важно для Vue 3, потому что binding.expression больше не является частью API пользовательских директив. Для Vue 2 binding.value также поддерживается.
Важное ограничение
Callback сохраняется в обработчике при первичном подключении директивы.
Это нормально для стабильного callback:
<div v-click-outside="closeMenu">
Menu
</div>Но если callback может динамически заменяться после монтирования компонента, текущая реализация может продолжить вызывать старую функцию.
Пример рискованного сценария:
<template>
<div v-click-outside="currentOutsideHandler">
Content
</div>
</template>Если currentOutsideHandler меняется во время жизни компонента, директиве может потребоваться дополнительный update hook для Vue 2 и Vue 3, чтобы обновлять сохраненный callback.
Установка
npm install @ttbooking/vue-click-outside-directiveИспользование с Vue 2
Глобальная регистрация:
import Vue from "vue";
import clickOutside from "@ttbooking/vue-click-outside-directive";
Vue.directive("click-outside", clickOutside);Использование в компоненте:
<template>
<div v-click-outside="close">
<button @click="isOpen = !isOpen">Toggle</button>
<div v-if="isOpen">
Dropdown content
</div>
</div>
</template>
<script>
export default {
data() {
return {
isOpen: false,
};
},
methods: {
close(event) {
this.isOpen = false;
},
},
};
</script>Локальная регистрация:
import clickOutside from "@ttbooking/vue-click-outside-directive";
export default {
directives: {
clickOutside,
},
};Использование с Vue 3
Глобальная регистрация:
import { createApp } from "vue";
import App from "./App.vue";
import clickOutside from "@ttbooking/vue-click-outside-directive";
const app = createApp(App);
app.directive("click-outside", clickOutside);
app.mount("#app");Использование в компоненте:
<template>
<div v-click-outside="close">
<button @click="isOpen = !isOpen">Toggle</button>
<div v-if="isOpen">
Dropdown content
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
const isOpen = ref(false);
function close(event) {
isOpen.value = false;
}
</script>Локальная регистрация в Options API:
<script>
import clickOutside from "@ttbooking/vue-click-outside-directive";
export default {
directives: {
clickOutside,
},
};
</script>Поведение при клике по scrollbar
Директива пытается не вызывать callback при клике по scrollbar. Это нужно, чтобы прокрутка страницы или контейнера не воспринималась как внешний клик.
API
Директива ожидает функцию:
<div v-click-outside="handler" />function handler(event) {
// event - исходный MouseEvent
}Если в директиву передано не значение типа function, callback вызван не будет.
