Задать вопрос
@Goodie128

Как использовать :key в пользовательской директиве?

Добрый день. Хочу написать директиву, по которой при клике вне элемента закрывается сам элемент (фильтр). Но суть в том, что у меня этих фильтров несколько (v-for), и при написании кода ниже, директива срабатывает сразу на всех элементах. И из-за этого, очевидно, не открывается ни один фильтр. Как можно эту директиву приписать только к одному элементу (как-то использовать :key)?
app.directive('click-out', <Directive>{
  mounted(el, { value }) {
    el.clickOutsideEvent = (event: Event) => {
      if (el === event.target || el.contains(event.target)) {
        value(event);
      }
    };
    document.body.addEventListener('click', el.clickOutsideEvent);
  },
  unmounted(element) {
    document.body.removeEventListener('click', el.clickOutsideEvent);
  }
});
  • Вопрос задан
  • 83 просмотра
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 2
@MaxRyazan
напиши директиву отдельно от компонента и потом повесь на нужный элемент.
import {Directive, DirectiveBinding} from "vue";

export const clickOutside: Directive<HTMLElement, string> = {
    mounted(el: HTMLElement, bind: DirectiveBinding) {
        if(bind.value) {
            window.addEventListener('click', (e) => {
                if(!el.contains(<HTMLElement>e.target)) {
                   bind.value()
                }
            })
        }
    },
    unmounted: function (el: HTMLElement, bind: DirectiveBinding) {
        if(bind.value) {
            window.removeEventListener('click', (e) => {
                if(!el.contains(<HTMLElement>e.target)) {
                    bind.value()
                }
            })
        }
    }
}

Это общая директива. И затем вешаешь на любой компонент какой нужен на корневой div

<div v-click-outside="() => isFilterOpen = false">
   ....
 </div>


А твоя директива закрывает все сразу компоненты, потому что это логично. Если она работает на всех твоих фильтрах, то клик вне конкретного фильтра - его закрывает. Соответственно если у тебя открыты все сразу фильтры и ты кликнешь ГДЕ УГОДНО на странице, то закроются все фильтры сразу.
Конечно, если кликнуть на фильтре вместо "где угодно", то закроются все фильтры кроме того, на котором ты кликнул
Ответ написан
Aetae
@Aetae Куратор тега Vue.js
Тлен
Судя по названию директивы у тебя ошибка в логике:
if (el === event.target || el.contains(event.target)) {
->
if (el !== event.target && !el.contains(event.target)) {
->
if (!el.contains(event.target)) { 
// contains работает на самого себя, дополнительно проверять не надо

Мы ловим клик снаружи, т.е. не равный выбранному элементу, а у тебя ловится клик на самом элементе, т.е. как будто это простой @click.

Также по-хорошему следует предусмотреть update на случай обновления value, иначе у тебя директива поломается при его реактивном изменении(обычно конечно не меняют, но зачем закладывать бомбу?).
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы