웹에서 자주 쓰는 모달 컴포넌트에 대해서 포스팅을 해보고자 합니다.
강의를 들으면서 모달을 띄우는 것에 오류가 있었는데 해결을 해서 기쁘네요. 그럼 글 시작하겠습니다.
모달 컴포넌트 붙여넣기
Document
https://kr.vuejs.org/v2/examples/modal.html
도큐먼트는 다음 주소창으로 이동하면 나옵니다. 해당 도큐먼트에서 다음 코드들을 가져옵니다.
Modal Html 코드
<Transition name="modal">
<div class="modal-mask" v-if="showModal">
<div class="modal-wrapper">
<div class="modal-container">
<!-- modal header -->
<div class="modal-header">
<slot name="header"> default header </slot>
</div>
<!-- modal body -->
<div class="modal-body">
<slot name="body"> default body </slot>
</div>
<!-- modal footer-->
<div class="modal-footer">
<slot name="footer"> default footer </slot>
</div>
</div>
</div>
</div>
</Transition>
Modal CSS 코드
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: table;
transition: opacity 0.3s ease;
}
.modal-wrapper {
display: table-cell;
vertical-align: middle;
}
.modal-container {
width: 300px;
margin: 0px auto;
padding: 20px 30px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
transition: all 0.3s ease;
font-family: Helvetica, Arial, sans-serif;
}
.modal-header h3 {
margin-top: 0;
color: #42b983;
}
.modal-body {
margin: 20px 0;
}
.modal-default-button {
float: right;
}
/*
* The following styles are auto-applied to elements with
* transition="modal" when their visibility is toggled
* by Vue.js.
*
* You can easily play with the modal transition by editing
* these styles.
*/
.modal-enter-from {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
.modal-enter-from .modal-container,
.modal-leave-active .modal-container {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}
해당 코드들을 components 폴더 밑에 common 폴더를 만들어서 Modal.vue 파일에 복사 붙여넣기 합니다.
재사용성을 위하여 따로 common 폴더에 빼놓습니다.
components/common/Modal.vue
<template>
<Transition name="modal">
<div class="modal-mask" v-if="showModal">
<div class="modal-wrapper">
<div class="modal-container">
<!-- modal header -->
<div class="modal-header">
<slot name="header"> default header </slot>
</div>
<!-- modal body -->
<div class="modal-body">
<slot name="body"> default body </slot>
</div>
<!-- modal footer-->
<div class="modal-footer">
<slot name="footer"> default footer </slot>
</div>
</div>
</div>
</div>
</Transition>
</template>
<script>
export default {
props: ["showModal"],
};
</script>
<style>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: table;
transition: opacity 0.3s ease;
}
.modal-wrapper {
display: table-cell;
vertical-align: middle;
}
.modal-container {
width: 300px;
margin: 0px auto;
padding: 20px 30px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
transition: all 0.3s ease;
font-family: Helvetica, Arial, sans-serif;
}
.modal-header h3 {
margin-top: 0;
color: #42b983;
}
.modal-body {
margin: 20px 0;
}
.modal-default-button {
float: right;
}
/*
* The following styles are auto-applied to elements with
* transition="modal" when their visibility is toggled
* by Vue.js.
*
* You can easily play with the modal transition by editing
* these styles.
*/
.modal-enter-from {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
.modal-enter-from .modal-container,
.modal-leave-active .modal-container {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}
</style>
그러면 다음과 같습니다. 일단 Modal 컴포넌트를 만들었습니다.
모달 컴포넌트를 사용할 상위 컴포넌트 TodoInput
모달 컴포넌트 사용 - html
<!-- showModal 이 true 면 모달이 보인다-->
<!--close 이벤트가 되면 showModal이 false가 된다.-->
<Modal v-bind:showModal="showModal">
<template v-slot:header>
<h3>
경고!
<i class="fa-solid fa-xmark closeModalBtn" @click="showModal = false"></i>
</h3>
</template>
<template #body>할 일을 입력해주세요.</template>
<template #footer>copy right</template>
</Modal>
showModal 데이터가 true 가 되면 Modal 컴포넌트가 보이게 됩니다.
모달 컴포넌트 사용 - js
data() {
return {
newTodoItem: "",
showModal: false,
};
},
showModal 데이터를 선언해야 이를 사용할 수 있습니다.
addTodo() {
// 값이 있을때만 실행
if (this.newTodoItem !== "") {
this.$emit("addTodoItem", this.newTodoItem);
this.clearInput();
} else {
this.showModal = true;
}
},
addTodo() 함수를 수정합니다.
else 구문을 붙여 만약 빈 칸을 입력하면 showModal 변수가 true 가 되도록 설정합니다.
slot
https://kr.vuejs.org/v2/guide/components-slots.html
slot 을 사용하면 재사용성이 좋아집니다.
<div class="modal-header">
<slot name="header"> default header </slot>
</div>
모달 컴포넌트에서 <slot></slot> 태그를 이용하여 선언된 곳의 내용을 사용자 나름대로 커스텀할 수 있습니다.
<template v-slot:header>
<h3>
경고!
<i class="fa-solid fa-xmark closeModalBtn" @click="showModal = false"></i>
</h3>
</template>
<template #body>할 일을 입력해주세요.</template>
<template #footer>copy right</template>
이는 상위 컴포넌트인 TodoInput 에서 변경이 가능합니다.
1. v-slot:"name"
<template v-slot:name> 커스텀 내용 </template>
2. #name
<template #name ></template>
이렇게 slot 을 사용할 때는 두 가지의 문법을 지켜야 합니다. 유의하시길 바랍니다.
components/TodoInput.vue
<template>
<div class="inputBox shadow">
<input type="text" v-model="newTodoItem" v-on:keyup.enter="addTodo" />
<span class="addContainer">
<i class="fa-solid fa-plus addBtn" v-on:click="addTodo"> </i>
</span>
<!-- showModal 이 true 면 모달이 보인다-->
<!--close 이벤트가 되면 showModal이 false가 된다.-->
<Modal v-bind:showModal="showModal">
<template v-slot:header>
<h3>
경고!
<i class="fa-solid fa-xmark closeModalBtn" @click="showModal = false"></i>
</h3>
</template>
<template #body>할 일을 입력해주세요.</template>
<template #footer>copy right</template>
</Modal>
</div>
</template>
<script>
import Modal from "./common/Modal.vue";
export default {
// data(): function() {}
data() {
return {
newTodoItem: "",
showModal: false,
};
},
components: {
Modal,
},
methods: {
// addTodo: function() {}
addTodo() {
// 값이 있을때만 실행
if (this.newTodoItem !== "") {
this.$emit("addTodoItem", this.newTodoItem);
this.clearInput();
} else {
this.showModal = true;
console.log(this.showModal);
}
},
clearInput() {
this.newTodoItem = "";
},
},
};
</script>
<style soped>
.hi {
background-color: #42b983;
}
input:focus {
outline: none;
}
.inputBox {
background: white;
height: 50px;
line-height: 50px;
border-radius: 5px;
}
.inputBox input {
border-style: none;
font-size: 0.9rem;
}
.addContainer {
float: right;
background: linear-gradient(to right, #6478fb, #8763fb);
display: block;
width: 3rem;
border-radius: 0 5px 5px 0;
}
.addBtn {
color: white;
vertical-align: middle;
}
.closeModalBtn {
color: #42b983;
}
</style>
또한 Modal 컴포넌트로 showModal 데이터를 전달해야지 모달 transition 을 사용할 수 있습니다.
그렇지 않으면 transition 이 제대로 동작하지 않습니다.
v-bind 를 통해 showModal 을 내려줍시다.
결과 화면
트랜지션과 모달이 제대로 동작하는 것을 확인할 수 있습니다. ✨
vue transition 오류
vue modal transition
vue modal
vue 모달
vue 모달 트랜지션
'🧶 𝗪𝗲𝗯 > Vue' 카테고리의 다른 글
[to-do-app] Vue Transition (0) | 2022.02.26 |
---|---|
[to-do-app] 리팩토링: 할 일 모두 삭제 기능 (0) | 2022.02.24 |
[to-do-app] 리팩토링: 할 일 완료 기능 (0) | 2022.02.24 |
[to-do-app] 리팩토링: 할 일 삭제 기능 (0) | 2022.02.24 |
[to-do-app] 리팩토링: 할 일 추가 기능 (0) | 2022.02.24 |