Vue stopPropagation 不工作 - child 到 parent
Vue stopPropagation not working - child to parent
我正在努力处理事件传播。如果数据未保存,任务是防止点击任何其他内容。所以,左边 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();
},
无论如何,点击都会传播到 parent。如果我将事件 @click
放入 parent,它会触发所有点击。
停止传播是否只在parent到children之间起作用?
我不熟悉 v-click-outside
实现,但是 "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-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 提交拉取请求以支持此功能?
我正在努力处理事件传播。如果数据未保存,任务是防止点击任何其他内容。所以,左边 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();
},
无论如何,点击都会传播到 parent。如果我将事件 @click
放入 parent,它会触发所有点击。
停止传播是否只在parent到children之间起作用?
我不熟悉 v-click-outside
实现,但是 "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-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 提交拉取请求以支持此功能?