Vue Click Outside Directive
June 24, 2021•250 words
src/directives/ClickOutside.js
First, create a directive
/**
* A simple Vue directive to trigger an event when the user
* clicks anywhere other than the specified element.
* Used to close context menu's popup menus and tips.
*/
const instances = [];
function onDocumentClick(e, el, fn) {
const { target } = e;
if (el !== target && !el.contains(target)) {
fn(e);
}
}
export default {
bind(element, binding) {
const el = element;
el.dataset.outsideClickIndex = instances.length;
const fn = binding.value;
const click = (e) => {
onDocumentClick(e, el, fn);
};
document.addEventListener('click', click);
document.addEventListener('touchstart', click);
instances.push(click);
},
unbind(el) {
const index = el.dataset.outsideClickIndex;
const handler = instances[index];
document.removeEventListener('click', handler);
instances.splice(index, 1);
},
};
src/main.js
Next, in your Vue.js main file, register that directive
import Vue from 'vue';
import App from '@/App.vue';
import clickOutside from '@/utils/ClickOutside';
Vue.directive('clickOutside', clickOutside);
new Vue({
render: (awesome) => awesome(App),
}).$mount('#app');
src/components/SomeComponent.vue
Finally, we can use are directive to call a function when the user clicks anywhere other than the specified element. In this example, I'm going to be hiding a small pop-up menu
<template ref="container">
<div class="item-wrapper">
<p>Some other content...</p>
<ContextMenu v-if="contextMenuOpen" v-click-outside="closeContextMenu" />
</div>
</template>
<script>
import ContextMenu from '@/components/LinkItems/ContextMenu';
export default {
name: 'Item',
props: {
...
},
data() {
return {
contextMenuOpen: false,
};
},
components: {
ContextMenu,
},
methods: {
openContextMenu(event) {
this.contextMenuOpen = !this.contextMenuOpen || true;
console.log('Right clicked!', event);
},
closeContextMenu() {
this.contextMenuOpen = false;
},
},
};
</script>
<style scoped lang="scss">
...
</style>