Wykryj kliknięcie elementu zewnętrznego

121

Jak mogę wykryć kliknięcie poza moim elementem? Używam Vue.js, więc będzie poza moim elementem szablonów. Wiem, jak to zrobić w Vanilla JS, ale nie jestem pewien, czy istnieje lepszy sposób na zrobienie tego, gdy używam Vue.js?

To jest rozwiązanie dla zdarzenia Vanilla JS: wykrywanie kliknięć JavaScript poza div

Myślę, że mogę użyć lepszego sposobu na dostęp do elementu?

Społeczność
źródło
Komponenty Vue są izolowane. więc wykrywanie zmian zewnętrznych jest wykluczone i używany jest anty-wzorzec.
Raj Kamal
Dzięki. Nie jestem jednak pewien, jak zaimplementować to w komponencie Vue. Nadal muszą istnieć dobre praktyki dotyczące anty-wzorca?
Komponenty Vue.js są izolowane, to prawda, ale istnieją różne metody komunikacji rodzic-dziecko. Tak więc, zamiast pytać wykryć poza przypadku elementu, należy określić, czy chcesz, aby wykryć elementy wewnątrz komponentu, z elementu nadrzędnego, z jakimś dzieckiem, czy cokolwiek jest relacja pomiędzy komponentami
Yerko Palma
Dziękujemy za opinię. Czy masz jakieś przykłady lub linki, którymi mogę się zająć?
github.com/simplesmiler/vue-clickaway może uprościć Twoją pracę
Raj Kamal

Odpowiedzi:

97

Można to ładnie rozwiązać, konfigurując raz dyrektywę niestandardową:

Vue.directive('click-outside', {
  bind () {
      this.event = event => this.vm.$emit(this.expression, event)
      this.el.addEventListener('click', this.stopProp)
      document.body.addEventListener('click', this.event)
  },   
  unbind() {
    this.el.removeEventListener('click', this.stopProp)
    document.body.removeEventListener('click', this.event)
  },

  stopProp(event) { event.stopPropagation() }
})

Stosowanie:

<div v-click-outside="nameOfCustomEventToCall">
  Some content
</div>

W komponencie:

events: {
  nameOfCustomEventToCall: function (event) {
    // do something - probably hide the dropdown menu / modal etc.
  }
}

Działające demo na JSFiddle z dodatkowymi informacjami o zastrzeżeniach:

https://jsfiddle.net/Linusborg/yzm8t8jq/

Linus Borg
źródło
3
Użyłem vue clickaway, ale myślę, że twoje rozwiązanie jest mniej więcej takie samo. Dzięki.
56
To podejście już nie działa w Vue.js 2. Wywołanie self.vm. $ emit wyświetla komunikat o błędzie.
Northernman
3
Użycie @blur również jest opcją i ułatwia uzyskanie tego samego wyniku: <input @ blur = "hide"> gdzie hide: function () {this.isActive = false; }
Craws
1
Odpowiedź należy zredagować, aby stwierdzić, że dotyczy tylko Vue.js 1
Stéphane Gerber
167

Jest rozwiązanie, którego użyłem, które jest oparte na odpowiedzi Linusa Borga i działa dobrze z vue.js 2.0.

Vue.directive('click-outside', {
  bind: function (el, binding, vnode) {
    el.clickOutsideEvent = function (event) {
      // here I check that click was outside the el and his children
      if (!(el == event.target || el.contains(event.target))) {
        // and if it did, call method provided in attribute value
        vnode.context[binding.expression](event);
      }
    };
    document.body.addEventListener('click', el.clickOutsideEvent)
  },
  unbind: function (el) {
    document.body.removeEventListener('click', el.clickOutsideEvent)
  },
});

Łączysz się z nim za pomocą v-click-outside:

<div v-click-outside="doStuff">

Oto małe demo

Więcej informacji o dyrektywach niestandardowych i znaczeniu el, bind, vnode można znaleźć w https://vuejs.org/v2/guide/custom-directive.html#Directive-Hook-Arguments

MadisonTrash
źródło
8
Działało, ale w dyrektywach Vue 2.0 nie ma już instancji, więc jest to niezdefiniowane. vuejs.org/v2/guide/migration.html#Custom-Directives-simplified . Nie mam pojęcia, dlaczego działają te skrzypce ani kiedy dokonano tego uproszczenia. (W celu rozwiązania wymienić „to” z „El”, aby powiązać zdarzenie elementu)
Busata
1
Działa prawdopodobnie dlatego, że okno przeszło jako „to”. Naprawiłem odpowiedź. Dziękuję za wskazanie tego błędu.
MadisonTrash
8
Czy istnieje sposób na wykluczenie określonego elementu na zewnątrz? Na przykład mam jeden przycisk na zewnątrz, który musi otworzyć ten element, a ponieważ wyzwala obie metody, nic się nie dzieje.
Žilvinas
5
Czy możesz wyjaśnić vnode.context [bind.expression] (event); ?
Sainath SR
1
jak to zmienić, aby można było użyć wyrażenia zamiast metody w ramach v-click-outside?
raphadko
50

Dodaj tabindexatrybut do komponentu, aby można było na nim skupić się i wykonaj następujące czynności:

<template>
    <div
        @focus="handleFocus"
        @focusout="handleFocusOut"
        tabindex="0"
    >
      SOME CONTENT HERE
    </div>
</template>

<script>
export default {    
    methods: {
        handleFocus() {
            // do something here
        },
        handleFocusOut() {
            // do something here
        }
    }
}
</script>
G'ofur N
źródło
4
Whoa! Uważam to za najkrótsze i najczystsze rozwiązanie. Również jedyny, który zadziałał w moim przypadku.
Matt Komarnicki
3
Aby to dodać, ustawienie indeksu tabulatora na -1 spowoduje, że po kliknięciu elementu nie pojawi się zaznaczenie, ale nadal będzie można ustawić fokus na div.
Colin
1
Z jakiegoś powodu tabindex -1 nie ukrywa dla mnie konturu, więc właśnie dodałem outline: none;fokus dla elementu.
Art3mix
1
jak możemy to zastosować do bocznej nawigacji poza płótnem, która przesuwa się po ekranie? Nie mogę ustawić ostrości sidenav, dopóki nie zostanie kliknięty,
Charles Okwuagwu
1
Jest to absolutnie najpotężniejszy sposób. Dziękuję Ci! :)
Canet Robern
23

W społeczności dostępne są dwa pakiety do tego zadania (oba są obsługiwane):

Julien Le Coupanec
źródło
8
vue-clickawayPakiet doskonale rozwiązał mój problem. Dzięki
Abdalla Arbab
1
A co z wieloma przedmiotami? Każdy element ze zdarzeniem zewnętrznego kliknięcia będzie uruchamiał zdarzenie przy każdym kliknięciu. Fajnie, kiedy tworzysz okno dialogowe, a strasznie, kiedy tworzysz galerię. W erze non-component nasłuchujemy kliknięcia z dokumentu i sprawdzamy, który element został kliknięty. Ale teraz to ból.
br.
@Julien Le Coupanec To rozwiązanie jest zdecydowanie najlepsze! Wielkie dzięki za udostępnienie!
Manuel Abascal
7

To zadziałało dla mnie z Vue.js 2.5.2:

/**
 * Call a function when a click is detected outside of the
 * current DOM node ( AND its children )
 *
 * Example :
 *
 * <template>
 *   <div v-click-outside="onClickOutside">Hello</div>
 * </template>
 *
 * <script>
 * import clickOutside from '../../../../directives/clickOutside'
 * export default {
 *   directives: {
 *     clickOutside
 *   },
 *   data () {
 *     return {
         showDatePicker: false
 *     }
 *   },
 *   methods: {
 *     onClickOutside (event) {
 *       this.showDatePicker = false
 *     }
 *   }
 * }
 * </script>
 */
export default {
  bind: function (el, binding, vNode) {
    el.__vueClickOutside__ = event => {
      if (!el.contains(event.target)) {
        // call method provided in v-click-outside value
        vNode.context[binding.expression](event)
        event.stopPropagation()
      }
    }
    document.body.addEventListener('click', el.__vueClickOutside__)
  },
  unbind: function (el, binding, vNode) {
    // Remove Event Listeners
    document.removeEventListener('click', el.__vueClickOutside__)
    el.__vueClickOutside__ = null
  }
}
yann_yinn
źródło
Dziękuję za ten przykład. Sprawdziłem to w wersji 2.6. Jest jakaś poprawka, w metodzie unbind musisz naprawić jakiś problem przez to (zapomniałeś właściwości body w metodzie unbind): document.body.removeEventListener ('click', el .__ vueClickOutside__); jeśli nie - spowoduje utworzenie wielu detektorów zdarzeń po każdym odtworzeniu komponentu (odświeżeniu strony);
Alexey Shabramov
7
export default {
  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

  }
}
xiaoyu2er
źródło
5

Połączyłem wszystkie odpowiedzi (w tym wiersz z vue-clickaway) i wymyśliłem to rozwiązanie, które działa dla mnie:

Vue.directive('click-outside', {
    bind(el, binding, vnode) {
        var vm = vnode.context;
        var callback = binding.value;

        el.clickOutsideEvent = function (event) {
            if (!(el == event.target || el.contains(event.target))) {
                return callback.call(vm, event);
            }
        };
        document.body.addEventListener('click', el.clickOutsideEvent);
    },
    unbind(el) {
        document.body.removeEventListener('click', el.clickOutsideEvent);
    }
});

Użyj w komponencie:

<li v-click-outside="closeSearch">
  <!-- your component here -->
</li>
BogdanG
źródło
Prawie to samo, co odpowiedź @MadisonTrash poniżej
retrovertigo
3

Zaktualizowałem odpowiedź MadisonTrash, aby obsługiwała Mobile Safari (która nie ma clickzdarzenia, touchendmusi być używana zamiast tego). Obejmuje to również sprawdzenie, aby zdarzenie nie było wyzwalane przez przeciąganie na urządzeniach mobilnych.

Vue.directive('click-outside', {
    bind: function (el, binding, vnode) {
        el.eventSetDrag = function () {
            el.setAttribute('data-dragging', 'yes');
        }
        el.eventClearDrag = function () {
            el.removeAttribute('data-dragging');
        }
        el.eventOnClick = function (event) {
            var dragging = el.getAttribute('data-dragging');
            // Check that the click was outside the el and its children, and wasn't a drag
            if (!(el == event.target || el.contains(event.target)) && !dragging) {
                // call method provided in attribute value
                vnode.context[binding.expression](event);
            }
        };
        document.addEventListener('touchstart', el.eventClearDrag);
        document.addEventListener('touchmove', el.eventSetDrag);
        document.addEventListener('click', el.eventOnClick);
        document.addEventListener('touchend', el.eventOnClick);
    }, unbind: function (el) {
        document.removeEventListener('touchstart', el.eventClearDrag);
        document.removeEventListener('touchmove', el.eventSetDrag);
        document.removeEventListener('click', el.eventOnClick);
        document.removeEventListener('touchend', el.eventOnClick);
        el.removeAttribute('data-dragging');
    },
});
benrwb
źródło
3

Używam tego kodu:

przycisk pokaż-ukryj

 <a @click.stop="visualSwitch()"> show hide </a>

element pokaż-ukryj

<div class="dialog-popup" v-if="visualState" @click.stop=""></div>

scenariusz

data () { return {
    visualState: false,
}},
methods: {
    visualSwitch() {
        this.visualState = !this.visualState;
        if (this.visualState)
            document.addEventListener('click', this.visualState);
        else
            document.removeEventListener('click', this.visualState);
    },
},

Aktualizacja: usuń zegarek; dodać stop propagację

Pax Exterminatus
źródło
2

Nienawidzę dodatkowych funkcji, więc ... oto niesamowite rozwiązanie vue bez dodatkowych metod vue, tylko var

  1. utwórz element html, ustaw kontrolki i dyrektywę
    <p @click="popup = !popup" v-out="popup">

    <div v-if="popup">
       My awesome popup
    </div>
  1. stworzyć zmienną w danych, takich jak
data:{
   popup: false,
}
  1. dodaj dyrektywę vue. jego
Vue.directive('out', {

    bind: function (el, binding, vNode) {
        const handler = (e) => {
            if (!el.contains(e.target) && el !== e.target) {
                //and here is you toggle var. thats it
                vNode.context[binding.expression] = false
            }
        }
        el.out = handler
        document.addEventListener('click', handler)
    },

    unbind: function (el, binding) {
        document.removeEventListener('click', el.out)
        el.out = null
    }
})
Martin Prestone
źródło
2

Jeśli szukasz kliknięcia poza elementem, ale nadal w obrębie elementu nadrzędnego, możesz użyć

<div class="parent" @click.self="onParentClick">
  <div class="child"></div>
</div>

Używam tego do modali.

Andres Holguin
źródło
1

Możesz zarejestrować dwa detektory zdarzeń dla takiego zdarzenia kliknięcia

document.getElementById("some-area")
        .addEventListener("click", function(e){
        alert("You clicked on the area!");
        e.stopPropagation();// this will stop propagation of this event to upper level
     }
);

document.body.addEventListener("click", 
   function(e) {
           alert("You clicked outside the area!");
         }
);
saravanakumar
źródło
Dzięki. Wiem o tym, ale wydaje się, że w Vue.js musi być lepszy sposób na zrobienie tego?
DOBRZE! niech jakiś geniusz vue.js odpowie :)
saravanakumar
1
  <button 
    class="dropdown"
    @click.prevent="toggle"
    ref="toggle"
    :class="{'is-active': isActiveEl}"
  >
    Click me
  </button>

  data() {
   return {
     isActiveEl: false
   }
  }, 
  created() {
    window.addEventListener('click', this.close);
  },
  beforeDestroy() {
    window.removeEventListener('click', this.close);
  },
  methods: {
    toggle: function() {
      this.isActiveEl = !this.isActiveEl;
    },
    close(e) {
      if (!this.$refs.toggle.contains(e.target)) {
        this.isActiveEl = false;
      }
    },
  },
Dmytro Lishtvan
źródło
Dzięki, działa idealnie i jeśli potrzebujesz tego tylko raz, nie ma potrzeby tworzenia dodatkowych bibliotek
Marian Klühspies
1

Krótka odpowiedź: należy to zrobić za pomocą dyrektyw niestandardowych .

Jest tu wiele świetnych odpowiedzi, które również to mówią, ale większość odpowiedzi, które widziałem, załamuje się, gdy zaczniesz intensywnie korzystać z zewnętrznego kliknięcia (szczególnie warstwowego lub z wieloma wykluczeniami). Napisałem na medium artykuł, w którym mówiłem o niuansach dyrektyw niestandardowych, a konkretnie o implementacji tej. Może nie obejmuje wszystkich skrajnych przypadków, ale obejmuje wszystko, co wymyśliłem.

Uwzględni to wiele powiązań, wiele poziomów wykluczeń innych elementów i pozwoli programowi obsługi tylko zarządzać „logiką biznesową”.

Oto kod przynajmniej części definicji, zapoznaj się z artykułem, aby uzyskać pełne wyjaśnienie.

var handleOutsideClick={}
const OutsideClick = {
  // this directive is run on the bind and unbind hooks
  bind (el, binding, vnode) {
    // Define the function to be called on click, filter the excludes and call the handler
    handleOutsideClick[el.id] = e => {
      e.stopPropagation()
      // extract the handler and exclude from the binding value
      const { handler, exclude } = binding.value
      // set variable to keep track of if the clicked element is in the exclude list
      let clickedOnExcludedEl = false
      // if the target element has no classes, it won't be in the exclude list skip the check
      if (e.target._prevClass !== undefined) {
        // for each exclude name check if it matches any of the target element's classes
        for (const className of exclude) {
          clickedOnExcludedEl = e.target._prevClass.includes(className)
          if (clickedOnExcludedEl) {
            break // once we have found one match, stop looking
          }
        }
      }
      // don't call the handler if our directive element contains the target element
      // or if the element was in the exclude list
      if (!(el.contains(e.target) || clickedOnExcludedEl)) {
        handler()
      }
    }
    // Register our outsideClick handler on the click/touchstart listeners
    document.addEventListener('click', handleOutsideClick[el.id])
    document.addEventListener('touchstart', handleOutsideClick[el.id])
    document.onkeydown = e => {
      //this is an option but may not work right with multiple handlers
      if (e.keyCode === 27) {
        // TODO: there are minor issues when escape is clicked right after open keeping the old target
        handleOutsideClick[el.id](e)
      }
    }
  },
  unbind () {
    // If the element that has v-outside-click is removed, unbind it from listeners
    document.removeEventListener('click', handleOutsideClick[el.id])
    document.removeEventListener('touchstart', handleOutsideClick[el.id])
    document.onkeydown = null //Note that this may not work with multiple listeners
  }
}
export default OutsideClick
Marcus Smith
źródło
1

Zrobiłem to w nieco inny sposób, używając funkcji w obrębie created ().

  created() {
      window.addEventListener('click', (e) => {
        if (!this.$el.contains(e.target)){
          this.showMobileNav = false
        }
      })
  },

W ten sposób, jeśli ktoś kliknie poza elementem, to w moim przypadku nawigacja mobilna jest ukryta.

Mam nadzieję że to pomoże!

Prawie Pitt
źródło
1

Istnieje już wiele odpowiedzi na to pytanie, a większość z nich opiera się na podobnej idei dyrektywy celnej. Problem z tym podejściem polega na tym, że trzeba przekazać funkcję metody do dyrektywy i nie można bezpośrednio pisać kodu, jak w innych zdarzeniach.

Utworzyłem nowy pakiet, vue-on-clickoutktóry jest inny. Sprawdź to na:

Pozwala pisać v-on:clickoutjak każde inne wydarzenie. Na przykład możesz pisać

<div v-on:clickout="myField=value" v-on:click="myField=otherValue">...</div>

i to działa.

Aktualizacja

vue-on-clickout obsługuje teraz Vue 3!

Mu-Tsun Tsai
źródło
0

Tylko jeśli ktoś szuka sposobu na ukrycie modalu po kliknięciu poza modalem. Ponieważ modal zwykle ma opakowanie z klasą modal-wraplub jakąkolwiek inną nazwą, możesz ją założyć @click="closeModal". Używając obsługi zdarzeń opisanej w dokumentacji vuejs, możesz sprawdzić, czy kliknięty cel znajduje się w opakowaniu, czy w module.

methods: {
  closeModal(e) {
    this.event = function(event) {
      if (event.target.className == 'modal-wrap') {
        // close modal here
        this.$store.commit("catalog/hideModal");
        document.body.removeEventListener("click", this.event);
      }
    }.bind(this);
    document.body.addEventListener("click", this.event);
  },
}
<div class="modal-wrap" @click="closeModal">
  <div class="modal">
    ...
  </div>
<div>

jedi
źródło
0

Rozwiązania @Denis Danilenko działają dla mnie, oto co zrobiłem: Przy okazji używam VueJS CLI3 i NuxtJS tutaj oraz z Bootstrap4, ale będzie działać również na VueJS bez NuxtJS:

<div
    class="dropdown ml-auto"
    :class="showDropdown ? null : 'show'">
    <a 
        href="#" 
        class="nav-link" 
        role="button" 
        id="dropdownMenuLink" 
        data-toggle="dropdown" 
        aria-haspopup="true" 
        aria-expanded="false"
        @click="showDropdown = !showDropdown"
        @blur="unfocused">
        <i class="fas fa-bars"></i>
    </a>
    <div 
        class="dropdown-menu dropdown-menu-right" 
        aria-labelledby="dropdownMenuLink"
        :class="showDropdown ? null : 'show'">
        <nuxt-link class="dropdown-item" to="/contact">Contact</nuxt-link>
        <nuxt-link class="dropdown-item" to="/faq">FAQ</nuxt-link>
    </div>
</div>
export default {
    data() {
        return {
            showDropdown: true
        }
    },
    methods: {
    unfocused() {
        this.showDropdown = !this.showDropdown;
    }
  }
}
alfieindesigns
źródło
0

Możesz emitować niestandardowe natywne zdarzenie javascript z dyrektywy. Utwórz dyrektywę, która wywołuje zdarzenie z węzła, używając node.dispatchEvent

let handleOutsideClick;
Vue.directive('out-click', {
    bind (el, binding, vnode) {

        handleOutsideClick = (e) => {
            e.stopPropagation()
            const handler = binding.value

            if (el.contains(e.target)) {
                el.dispatchEvent(new Event('out-click')) <-- HERE
            }
        }

        document.addEventListener('click', handleOutsideClick)
        document.addEventListener('touchstart', handleOutsideClick)
    },
    unbind () {
        document.removeEventListener('click', handleOutsideClick)
        document.removeEventListener('touchstart', handleOutsideClick)
    }
})

Które można wykorzystać w ten sposób

h3( v-out-click @click="$emit('show')" @out-click="$emit('hide')" )
Pedro Torchio
źródło
0

Tworzę element div na końcu ciała w ten sposób:

<div v-if="isPopup" class="outside" v-on:click="away()"></div>

Gdzie .outside jest:

.outside {
  width: 100vw;
  height: 100vh;
  position: fixed;
  top: 0px;
  left: 0px;
}

A away () to metoda w instancji Vue:

away() {
 this.isPopup = false;
}

Spokojnie, działa dobrze.

Arnaud LiDz
źródło
0

Jeśli masz komponent z wieloma elementami wewnątrz elementu głównego, możesz użyć tego rozwiązania It just works ™ z wartością logiczną.

<template>
  <div @click="clickInside"></div>
<template>
<script>
export default {
  name: "MyComponent",
  methods: {
    clickInside() {
      this.inside = true;
      setTimeout(() => (this.inside = false), 0);
    },
    clickOutside() {
      if (this.inside) return;
      // handle outside state from here
    }
  },
  created() {
    this.__handlerRef__ = this.clickOutside.bind(this);
    document.body.addEventListener("click", this.__handlerRef__);
  },
  destroyed() {
    document.body.removeEventListener("click", this.__handlerRef__);
  },
};
</script>
A1rPun
źródło
0

Użyj tego pakietu vue-click-outside

Jest prosty i niezawodny, obecnie używany przez wiele innych pakietów. Możesz również zmniejszyć rozmiar pakietu javascript, wywołując pakiet tylko w wymaganych komponentach (patrz przykład poniżej).

npm install vue-click-outside

Stosowanie :

<template>
  <div>
    <div v-click-outside="hide" @click="toggle">Toggle</div>
    <div v-show="opened">Popup item</div>
  </div>
</template>

<script>
import ClickOutside from 'vue-click-outside'

export default {
  data () {
    return {
      opened: false
    }
  },

  methods: {
    toggle () {
      this.opened = true
    },

    hide () {
      this.opened = false
    }
  },

  mounted () {
    // prevent click outside event with popupItem.
    this.popupItem = this.$el
  },

  // do not forget this section
  directives: {
    ClickOutside
  }
}
</script>
Smit Patel
źródło
0

Nie odkrywaj na nowo koła, użyj tego pakietu v-click-outside

snehanshu.js
źródło
Sprawdź moją odpowiedź, którą podejrzewam, że polubisz ją bardziej.
Mu-Tsun Tsai
0

Możesz stworzyć nowy komponent, który będzie obsługiwał zewnętrzne kliknięcie

Vue.component('click-outside', {
  created: function () {
    document.body.addEventListener('click', (e) => {
       if (!this.$el.contains(e.target)) {
            this.$emit('clickOutside');
           
        })
  },
  template: `
    <template>
        <div>
            <slot/>
        </div>
    </template>
`
})

I użyj tego komponentu:

<template>
    <click-outside @clickOutside="console.log('Click outside Worked!')">
      <div> Your code...</div>
    </click-outside>
</template>
Dyktator 47
źródło
-1

często ludzie chcą wiedzieć, czy użytkownik opuścił komponent root (działa z dowolnymi komponentami poziomu)

Vue({
  data: {},
  methods: {
    unfocused : function() {
      alert('good bye');
    }
  }
})
<template>
  <div tabindex="1" @blur="unfocused">Content inside</div>
</template>

Denis Danilenko
źródło
-1

Mam rozwiązanie do obsługi menu przełączania rozwijanego:

export default {
data() {
  return {
    dropdownOpen: false,
  }
},
methods: {
      showDropdown() {
        console.log('clicked...')
        this.dropdownOpen = !this.dropdownOpen
        // this will control show or hide the menu
        $(document).one('click.status', (e)=> {
          this.dropdownOpen = false
        })
      },
}
Nicolas S.Xu
źródło
-1

Używam tego pakietu: https://www.npmjs.com/package/vue-click-outside

U mnie działa dobrze

HTML:

<div class="__card-content" v-click-outside="hide" v-if="cardContentVisible">
    <div class="card-header">
        <input class="subject-input" placeholder="Subject" name=""/>
    </div>
    <div class="card-body">
        <textarea class="conversation-textarea" placeholder="Start a conversation"></textarea>
    </div>
</div>

Moje kody skryptów:

import ClickOutside from 'vue-click-outside'
export default
{
    data(){
        return {
            cardContentVisible:false
        }
    },
    created()
    {
    },
    methods:
        {
            openCardContent()
            {
                this.cardContentVisible = true;
            }, hide () {
            this.cardContentVisible = false
                }
        },
    directives: {
            ClickOutside
    }
}
Murad Shukurlu
źródło