Без добавления дополнительных зависимостей в ваш проект

Недавно я столкнулся с этой проблемой, когда у меня был тумблер для отображения меню, но когда я щелкнул другую часть страницы, меню не исчезло. Я понял, что существуют библиотеки, такие как эта https://github.com/simplesmiler/vue-clickaway, но я бы предпочел не использовать другую зависимость, если в этом нет необходимости. Я думал, что поделюсь одним беззависимым способом скрыть меню, когда пользователь щелкает от переключателя.

В новом проекте vue я начал с простого переключателя, который показывает или скрывает меню:

Чтобы получить простое меню переключения выше, я изменил App.vue на это:

<template>
  <div class="toggle-container">
      <button class="toggle" @click="toggle = !toggle">Toggle</button>
  <div v-if="toggle">
    Menu
  </div>
  </div>
</template>
<script>
  export default {
    data () {
      return {
        toggle: false
      }
    },
  }
</script>
<style scoped>
.toggle-container {
  position: fixed; 
  top: 50%;
  left: 50%;
}
</style>

Это демонстрирует проблему - «Щелчок» на переключателе, когда меню открыто, не скроет меню снова.

Решение

Мы можем добавить прослушиватель событий для прослушивания события щелчка при создании компонента и один для случая, когда компонент отключен:

created() {
  window.addEventListener('click', this.close)
},
beforeUnmount() {
  window.removeEventListener('click', this.close)
},

Затем в событии закрытия мы можем проверить, была ли нажата кнопка переключения или вне ее, проверив this.$el (корневой элемент DOM):

close(e) {
  if (! this.$el.contains(e.target)) {
    this.active = false
  }
}

Вот как выглядит мой последний App.vue файл:

<template>
  <div class="toggle-container">
      <button class="toggle" @click="active = ! active">Toggle</button>
  <div v-if="active">
    Menu
  </div>
  </div>
</template>
<script>
  export default {
    data () {
      return {
        active: false
      }
    },
    created() {
      window.addEventListener('click', this.close)
    },
    beforeUnmount() {
      window.removeEventListener('click', this.close)
    },
    methods: {
      close(e) {
        if (! this.$el.contains(e.target)) {
          this.active = false
        }
      }
    }
  }
</script>
<style scoped>
.toggle-container {
  position: fixed; 
  top: 50%;
  left: 50%;
}
</style>

Мне лично нравится это решение, потому что оно довольно простое и позволяет избежать дополнительных зависимостей. Надеюсь, это поможет вам в вашем проекте!