Vue stopPropagation не работает - дочерний элемент к родительскому элементу
Я борюсь с распространением событий. Задача состоит в том, чтобы не нажимать на что-либо еще, если данные не сохранены. Итак, левый div содержит дерево опций. После нажатия на элемент отображается настройка в правом div. Я хочу предупредить пользователя, когда он пытается щелкнуть за пределами настроек div, что данные не сохраняются.
Код выглядит так:
<div class="row">
<div class="col-sm-6">
<tree
:data="treeData">
.. some tree data
</tree>
</div>
<div class="col-sm-6">
<div class="treeOptionEdit" v-if="showEditBox" v-click-outside.stop="checkIfSaved">
... setting input fields
vue-outside-events
Пакет используется для обнаружения кликов за пределами div. Работает нормально. Проблема в том, что этот код ничего не делает:
checkIfSaved : function (event, el)
{
event.stopPropagation();
event.preventDefault();
},
В любом случае щелчок распространяется на родителя. Если я поставлю событие @click
к родителю, это произведено все щелчки.
Работает ли остановка распространения только от родителей к детям?
1 ответ
Я не знаком с v-click-outside
реализации, но события "щелчка снаружи" обычно реализуются с помощью делегирования события в элементе document/body, и поэтому к этому времени событие уже распространилось и не может быть остановлено.
Вот небольшой пример того, что происходит:
Vue.directive('click-outside', {
bind(el, { value }) {
el._handler = e => {
if (!el.contains(e.target)) {
value(e);
}
};
document.addEventListener('click', el._handler);
},
unbind(el) {
document.removeEventListener('click', el._handler);
},
});
new Vue({
el: '#app',
methods: {
onClick(e, color) {
alert(`Clicked the ${color} box.`);
},
onClickOutside(e, color) {
e.stopPropagation();
alert(`Clicked outside of ${color} box.`);
},
},
});
.box { padding: 20px; }
.red { background-color: red; }
.yellow { background-color: yellow; }
.blue { background-color: blue; }
<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>
<div id="app">
<div class="box red" @click="onClick($event, 'red')">
<div class="box yellow" @click="onClick($event, 'yellow')">
<div class="box blue" @click="onClick($event, 'blue')" v-click-outside="e => onClickOutside(e, 'blue')">
</div>
</div>
</div>
</div>
- Нажмите синюю коробку. Синее поле сначала получает событие щелчка, затем оно всплывает до желтого, а затем красного поля, как и ожидалось.
- Нажмите на желтое поле. Желтые, а затем красные прямоугольники получают событие click, затем, как только оно всплывает к элементу документа (из которых
click-outside
Директива прикрепила слушатель события)click-outside
обработчик называется. призваниеstopPropagation()
в этот момент ничего не происходит, потому что событие уже достигло вершины.
Я не верю .stop
Модификатор делает что-нибудь в вашем примере, потому что v-click-outside
не поддерживает этот модификатор (.stop
поддерживается только v-on
; v-click-outside
нужно было бы это поддержать).
Поэтому для решения вашей проблемы нужно изменить порядок событий: v-click-outside
должен быть обработан в первую очередь, прежде чем @click
,
Вы можете добиться этого, изменив v-click-outside
реализация с использованием захвата событий следующим образом:
Vue.directive('click-outside', {
bind(el, { value }) {
el._handler = e => {
if (!el.contains(e.target)) {
value(e);
}
};
// *** Using capturing ***
document.addEventListener('click', el._handler, { capture: true });
},
unbind(el) {
document.removeEventListener('click', el._handler, { capture: true });
},
});
new Vue({
el: '#app',
methods: {
onClick(e, color) {
alert(`Clicked the ${color} box.`);
},
onClickOutside(e, color) {
e.stopPropagation();
alert(`Clicked outside of ${color} box.`);
},
},
});
.box { padding: 20px; }
.red { background-color: red; }
.yellow { background-color: yellow; }
.blue { background-color: blue; }
<script src="https://rawgit.com/vuejs/vue/dev/dist/vue.js"></script>
<div id="app">
<div class="box red" @click="onClick($event, 'red')">
<div class="box yellow" @click="onClick($event, 'yellow')">
<div class="box blue" @click="onClick($event, 'blue')" v-click-outside="e => onClickOutside(e, 'blue')">
</div>
</div>
</div>
</div>
Почему бы не отправить запрос на включение в vue-outside-events для поддержки этой функции?