简体   繁体   中英

How do you handle click-outside of element properly in vuejs?

Is there any proper solution for handling click-outside of elements?

there are general solutions out there, like Handling clicks outside an element without jquery :

window.onload = function() {

    // For clicks inside the element
    document.getElementById('myElement').onclick = function(e) {
            // Make sure the event doesn't bubble from your element
        if (e) { e.stopPropagation(); } 
        else { window.event.cancelBubble = true; }
            // Place the code for this element here
        alert('this was a click inside');
    };

    // For clicks elsewhere on the page
    document.onclick = function() {
        alert('this was a click outside');
    };
};

But the problem is almost all projects have multiple and different popups in different components which i should handle their click-outsides.

how should i handle click-outisde without using a global window.on?(I think it is not possible to put all components outside-case handler in window.on )

After struggling with this and searching about this, i found how to solve this problem using vuejs directive without bleeding:

  1. using libraries:

v-click-outside is a good one,

https://www.npmjs.com/package/v-click-outside

  1. without a library:
     //main.js import '@/directives'; ...... // directives.js import Vue from "vue"; Vue.directive('click-outside', { bind: function (element, binding, vnode) { element.clickOutsideEvent = function (event) { // check that click was outside the el and his children if (!(element === event.target || element.contains(event.target))) { // and if it did, call method provided in attribute value vnode.context[binding.expression](event); // binding.value(); run the arg } }; document.body.addEventListener('click', element.clickOutsideEvent) }, unbind: function (element) { document.body.removeEventListener('click', element.clickOutsideEvent) } });

use it every-where you want with v-click-outside directive like below:

//header.vue
 <div class="profileQuickAction col-lg-4 col-md-12" v-click-outside="hidePopUps">
...
</>

you can check this on

You can also directly use VueUse vOnClickOUtside directive .

<script setup lang="ts">
import { vOnClickOutside } from '@vueuse/components'
const modal = ref(true)
function closeModal() {
  modal.value = false
}
</script>

<template>
  <div v-if="modal" v-on-click-outside="closeModal">
    Hello World
  </div>
</template>

It might be little late but i ve found a clear solution

<button class="m-search-btn" @click="checkSearch" v-bind:class="{'m-nav-active':search === true}">

methods:{
checkSearch(e){
  var clicked = e.target;
  this.search = !this.search;
  var that = this;
  window.addEventListener('click',function check(e){
    if (clicked === e.target || e.target.closest('.search-input')){ //I ve used target closest to protect the input that has search bar in it
      that.search = true;
    }else {
      that.search = false;
      removeEventListener('click',check)
    }
  })
}}


 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM