Detecting outside clicks is a common thing we need in almost all the apps that we build.
Having a reusable component to detect that is a great way to save time and help us focus on what we build.
Let me first show you the code of the component and explain how it works below. We’re going to call this component DetectOutsideClick.vue
.
<template>
<div ref="root">
<slot />
</div>
</template>
<script setup>
import { onMounted, onUnmounted, ref } from 'vue'
const emit = defineEmits(['detect'])
const root = ref(null)
const onClick = (e) => {
if (e.target === root.value || root.value.contains(e.target)) {
return
}
emit('detect')
}
onMounted(() => {
document.body.addEventListener('click', onClick)
})
onUnmounted(() => {
document.body.removeEventListener('click', onClick)
})
</script>
Here’s an example on how to use it:
<DetectOutsideClick @detect="onOutsideClick">
<div class="popup">A popup component</div>
</DetectOutsideClick>
How it works?
The idea here is to listen to all clicks on the page. If the clicked element is not the element inside <DetectOutsideClick>
or any children of it, then it’s an outside click.
We listen to all clicks on the page using this:
document.body.addEventListener('click', (e) => {})
And here’s how we check if it’s the same element or a child of it:
if (e.target === root.value || root.value.contains(e.target))
In this case we return
because it’s not an outside click. But if it is an outside click then we emit an event called detect
.
That’s it!