Почему бы вам просто не сделать выбранную проверку внутри обработчика щелчка снаружи?Вам также понадобится способ передать выбранный элемент обработчику.
<div id="list-item" v-on-click-outside="outSideClickHandler(item)"></div>
outSideClickHandler(item) {
return event => {
if (item.selected) {
// Handle the click outside
}
};
}
Вызовите обработчик в директиве следующим образом:
binding.value(event);
Вы не получаетеавтоматическая привязка «выражение / оператор» для пользовательских директив, например, вы используете v-on
, поэтому вам нужно каррировать функцию-обработчик, когда вы хотите передать ей дополнительные аргументы.
Под этим я подразумеваю аргументпереданный v-on
может быть выражением или оператором, например:
@click="handler" - handler is an expression (the function itself)
@click="handler(item)" - handler(item) is a statement
Но с помощью пользовательских директив вы можете только передавать выражения;вторая строка выше невозможна, если handler()
не возвращает другую функцию.
Я думаю, что есть некоторая путаница, потому что кажется, что вам нужно иметь пользовательскую директиву, которая используется только в этой конкретной ситуациис вашими элементами списка, но мое решение, приведенное выше, больше касается написания общей директивы "click outside", которую вы можете использовать в любой ситуации.
Также я думаю, что вы не хотите, чтобы директива регистрировала слушателей событий, еслиэлемент списка не выбран (по причинам производительности?).Если это так, то вместо этого вы можете использовать делегирование событий.
Нет способа условно включить / отключить директиву, вам придется сделать что-то вроде ответ Морти , оба из которыхэто немного грязно.
Это кажется работоспособным, но весь смысл использования пользовательских директив состоит в том, чтобы писать повторно используемый код манипуляции dom
Вы против написания кода манипуляции DOM внедирективы?Angular 1 имел эту философию.Если вы не хотите повторно использовать директиву в разных ситуациях, то может быть излишне писать директиву для этой ситуации просто так, чтобы «код манипулирования DOM не загрязнял мой компонент».Если я собираюсь написать директиву, то я бы хотел, чтобы она была как можно более общей, чтобы я мог использовать ее во многих различных ситуациях.
Мне даже не нужно передаватьпункт в этом случае.Потому что у меня есть компонент внутри v-for, а не div, и я связываю пользовательскую директиву с тем компонентом, обработчиком которого является метод
Тогда я не уверен, почему вы хотитереализовать это как директиву, которая редко нужна в любом случае.Вы можете просто зарегистрировать событие щелчка тела в хуке mounted
и удалить его в хуке destroyed
.Вся логика щелчка снаружи может содержаться в самом компоненте.
Если ваша основная задача - не регистрировать прослушиватель события щелчка тела для каждого элемента списка, вы можете сделать что-то вроде этого:
const handlers = new Map();
document.addEventListener('click', e => {
for (const handler of handlers.values()) {
handler(e);
}
});
Vue.directive('click-outside', {
bind(el, binding) {
const handler = e => {
if (el !== e.target && !el.contains(e.target)) {
binding.value(e);
}
};
handlers.set(el, handler);
},
unbind(el) {
handlers.delete(el);
},
});
Вы можете пойти еще дальше и автоматически добавить прослушиватель событий щелчка тела всякий раз, когда handlers
не пуст, и удалить прослушиватель, когда handlers
пусто.Вам решать.