v-click-outside directive https://jsfiddle.net/Linusborg/Lx49LaL8/
new Vue({
el: '#app',
data: {
clickOutside: 0,
clickInside: 0,
},
methods: {
outside: function(e) {
this.clickOutside += 1
console.log('clicked outside!')
},
inside: function(e) {
this.clickInside += 1
console.log('clicked inside!')
}
},
directives: {
'click-outside': {
bind: function(el, binding, vNode) {
// Provided expression must evaluate to a function.
if (typeof binding.value !== 'function') {
const compName = vNode.context.name
let warn = `[Vue-click-outside:] provided expression '${binding.expression}' is not a function, but has to be`
if (compName) { warn += `Found in component '${compName}'` }
console.warn(warn)
}
// Define Handler and cache it on the element
const bubble = binding.modifiers.bubble
const handler = (e) => {
if (bubble || (!el.contains(e.target) && el !== e.target)) {
binding.value(e)
}
}
el.__vueClickOutside__ = handler
// add Event Listeners
document.addEventListener('click', handler)
},
unbind: function(el, binding) {
// Remove Event Listeners
document.removeEventListener('click', el.__vueClickOutside__)
el.__vueClickOutside__ = null
}
}
}
})
<div id="app">
<div class="test" v-click-outside="outside" @click="inside">Test</div>
<!--<div class="test" v-click-outside.bubble="outside" @click="inside">Test</div>-->
Add the .bubble modifier to the directive to make clicks inside bubble up.
<pre>
{{$data}}
</pre>
</div>
.test {
padding: 50px;
border: 1px solid black;
margin: 50px;
background-color: white;
cursor: pointer;
}