Что такое Vue.js?

Vue.js — это JavaScript-фреймворк для создания пользовательских интерфейсов. Он строится на основе стандартных HTML, CSS и JavaScript и предоставляет декларативную и основанную на компонентах модель программирования, которая помогает вам эффективно разрабатывать пользовательские интерфейсы, будь то простые или сложные.

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

Это обычно используется на веб-страницах для обеспечения лучшего взаимодействия с пользователем.

Решение

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

давайте посмотрим на этот пример:

Во-первых, давайте создадим простую панель навигации, которая показывает некоторые параметры при нажатии:

Мы создадим компонент vue и назовем его NavIcon.vue.

Исходный код NavIcon.vue:

<script setup>
function toggleNav(e){
  e.target.classList.toggle("open")
} 
</script>

<template>
  <div class="menu" @click="toggleNav">
    <div class="button"></div>
    <div class="button"></div>
    <div class="button"></div>
</div>
</template>

Класс «open» отвечает за отображение или скрытие параметров навигации.

Для стиля я использую Sass, препроцессорный язык сценариев, который интерпретируется в CSS. Он содержит меньше кода, поэтому вы можете писать CSS быстрее.

Стиль компонента:

<style  lang="scss">

$icon-bg-color : #fdfdff;
html {
  background: #c7c7fc;
  height: 100vh;
  display: grid;
  place-content: center;
  -webkit-tap-highlight-color: transparent;
}

.menu {
  position: relative;
  top: 40px;
  padding: 30px;
  background: $icon-bg-color;
  border-radius: 100%;
  cursor: pointer;
  &::before, &::after {
    content: "";
    background: #c3c2c7;
    border-radius: 5px;
    width: 30px;
    height: 5px;
    position: absolute;
    left: 16px;
    top: 27px;
    transition: 0.2s ease;
    z-index: 1;
  }
  &::before {
    transform: rotate(0deg);
  }
  &::after {
    transform: rotate(-90deg);
  }
  &.open {
    opacity: .9;
    &::before {
      transform: rotate(45deg);
    }
    &::after {
      transform: rotate(-45deg);
    }
    .button {
      opacity: 1;
      pointer-events: auto;
      &:first-of-type {
        bottom: 40px;
        right: 70px;
        background: url("https://bassets.github.io/cam.svg") no-repeat 50%/50% $icon-bg-color;
      }
      &:nth-of-type(2) {
        bottom: 80px;
        background: url("https://bassets.github.io/img.svg") no-repeat 50%/ 50% $icon-bg-color;
        transition-delay: .05s;
      }
      &:last-of-type {
        bottom: 40px;
        right: -70px;
        background: url("https://bassets.github.io/music.svg") no-repeat 50% 45%/50% 45% $icon-bg-color;
        transition-delay: .1s;
      }
    }
  }
}

.button {
  padding: 30px;
  border-radius: 50%;
  cursor: pointer;
  background: #e8e8f3;
  position: absolute;
  bottom: 0;
  right: 0;
  opacity: 0;
  pointer-events: none;
  box-shadow: inherit;
  transition: 0.2s cubic-bezier(0.18, 0.89, 0.32, 1.28), 0.2s ease opacity, 0.2s cubic-bezier(.08,.82,.17,1) transform;
  &:hover {
    transform: scale(1.1);
  }
}
</style>

Компонент будет выглядеть так:

Обратите внимание, навигация скрыта только тогда, когда я нажимаю кнопку закрытия.

Мы хотим, чтобы он закрывался всякий раз, когда делается щелчок за пределами навигации.

Для этого мы добавим обработчик событий с обратным вызовом в документ дыры после того, как компонент будет полностью смонтирован в браузере.

При выполнении клика вызывается обратный вызов.

Обратный вызов имеет условие того, был ли щелчок от «div» или от одного из его дочерних элементов. В этом случае ничего делать не будем, Если условие ложно, то уберем из div класс «open», в ответ пропадет навигация.

Для этого нам нужно добавить следующий код:

Исходный код NavIcon.vue:

<script setup>
import { onMounted, ref } from "vue"

const navIcon = ref(null)

onMounted(()=>{
  document.addEventListener("click", (e)=>{
      if(e.target == navIcon.value || e.target.parentNode == navIcon.value) return
      navIcon.value.classList.remove("open")
  })
})

function toggleNav(e){
  e.target.classList.toggle("open")
} 
</script>

<template>
  <div class="menu" @click="toggleNav" ref="navIcon">
    <div class="button"></div>
    <div class="button"></div>
    <div class="button"></div>
</div>
</template>

Я использовал параметр ref, чтобы получить div из DOM, и хук onMounted, который регистрирует обратный вызов, который будет вызываться после монтирования компонента.

Результат:

Поздравляем, теперь мы успешно достигли нашей цели!

вы можете проверить исходный код здесь, на Github.

Спасибо за прочтение!