반응형
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에서도 동일합니다.
반응형