본문 바로가기

웹/VueJS

[Modern][vue3] dialog 태그를 활용한 로딩 바 구현

반응형

Modern 시리즈는 작성일 기준 최신 자바스크립트 문법으로 구현한 예제입니다.


<dialog>는 원래 모달을 구현하기 위해 제안된 스펙으로 2022년 3월에 HTML5의 기능으로 추가되었습니다.

모달을 위해 설계되긴 했지만 모달의 특성을 생각해보면 로딩으로 활용했을 때, 그 이점이 상당하다는 것을 알수 있습니다.

 

div 태그로 로딩 바를 구현해보시면 이벤트를 완전히 차단하는게 꽤나 피곤한 작업이란걸 아실겁니다.

backdrop 효과를 적용하기 위에 바깥에 div를 씌우고... 클릭 이벤트, 키보드 이벤트(tab 키 클릭), 스크롤 등 신경써야 할 부분이 상당히 많죠

dialog 태그를 이용해 로딩 바를 구현하면 많은 부분을 지원해주기 때문에 상당히 안정적입니다.

아래는 dialog가 지원해주는 기능입니다.

dialog Spec

  • 모달 창 뒤 배경의 상호작용 막기
  • 백드롭 적용(배경 흐리게 혹은 어둡게)

 

단, <dialog> 태그는 top-layer를 사용하므로 화면 맨 앞에 배치됩니다.

특정 컴포넌트의 위치에 작게 띄우는 로딩창이나 스켈레톤 UI의 경우 사용할 수 없습니다.

Loading.vue

<template>
  <dialog ref="loading" @close="model = false">
    <div class="spinner"></div>
  </dialog>
</template>

<script setup>
import { ref, watch, onMounted, defineModel } from 'vue'

const model = defineModel({ required: true })

const loading = ref(null)

onMounted(control)

watch(model, control)

function control() {
  if (model.value) loading.value.showModal()
  else loading.value.close()
}
</script>

<style scoped>
dialog {
  outline: none;
  border: none;

  background: transparent;
}

.spinner {
  display: flex;
  align-items: center;
  justify-content: center;

  --square-size: 48px;

  width: var(--square-size);
  height: var(--square-size);

  border: 5px solid #f3f3f3;
  border-top: 5px solid #3498db;
  border-radius: 50%;

  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
</style>

 

Loading 컴포넌트를 생성합니다.

해당 컴포넌트를 사용할 부분에서 Import한 후, bool 값을 v-model로 넘겨주면 됩니다.

사용하기

<template>
  <Loading v-model="loading" />
</template>

<script setup>
// 본인의 컴포넌트 경로를 작성하세요!
import Loading from '@/components/Loading/Loading.vue'
import { ref } from 'vue'

const loading = ref(false)
</script>

 

<dialog> 태그로 구현하면 로딩 밖의 상호작용을 자동으로 차단해줍니다.


아래 예시는 HTML로 작성했지만, 결과는 vue3에서도 동일합니다.

 

 

반응형