Vue 가 React 와 대비해 가지는 장점은 라이브러리 단에서 애니매이션과 트랜지션 등을 지원하는 것이다.
kr.vuejs.org/v2/examples/modal.html
- .vue 파일로 컴포넌트 모듈화할 때는 x-template 라는 개념이 나온다.
- id 값을 기준으로 Template 파일을 맵핑시켜 사용하는 것으로 필요한 컴포넌트에 등록하여 사용할 수 있다.
- #modal-template 의 id 값을 가지고 해당 Template 를 찾겠다는 것이다.
<!-- template for the modal component -->
<script type="text/x-template" id="modal-template">
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" @click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</script>
// register modal component
Vue.component('modal', {
template: '#modal-template'
})
// start app
new Vue({
el: '#app',
data: {
showModal: false
}
})
- data (){} 에 기술된 showModal이 트리거 이며 해당 boolean 값을 기준으로 v-if 디렉티브를 주어 끄거나 닫을 수 있다.
<!-- app -->
<div id="app">
<button id="show-modal" @click="showModal = true">Show Modal</button>
<!-- use the modal component, pass in the prop -->
<modal v-if="showModal" @close="showModal = false">
<!--
you can use custom content here to overwrite
default content
-->
<h3 slot="header">custom header</h3>
</modal>
</div>
사용 & 적용
따로 컴포넌트 화 시킨 Modal.vue
<template>
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" @click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</template>
<script>
export default {
name: "Modal"
}
</script>
<style scoped>
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
display: table;
transition: opacity .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, .33);
transition: all .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 {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
.modal-enter .modal-container,
.modal-leave-active .modal-container {
-webkit-transform: scale(1.1);
transform: scale(1.1);
}
</style>
사용하는 컴포넌트에 등록
- import 문으로 Modal 컴포넌트를 불러온다.
- Modal 컴포넌트를 사용하는 컴포넌트의 하위 컴포넌트로 지정한다.
- 태그이름은 Modal 컴포넌트 이름으로 맞춘다. ( 하위컴포넌트 사용방법과 동일 )
- data (){} 속성에 boolean 값으로 트리거를 준다.
<template>
<div class="inputBox shadow">
<input type="text" v-model="newTodoItem" v-on:keyup.enter="addTodo">
<!-- v-on:이벤트 = 실행메서드 -->
<span class="addContainer" v-on:click="addTodo">
<i class="fas fa-plus addBtn"></i>
</span>
<Modal v-if="showModal" @close="showModal = false">
<!--
you can use custom content here to overwrite
default content
-->
<h3 slot="header">custom header</h3>
</Modal>
</div>
</template>
<script>
import Modal from "./common/Modal";
export default {
data() {
return {
newTodoItem: "",
showModal : false
}
},
components: {
//ES6
Modal
},
methods: {
// 화살표 함수 쓰면 바인딩 잘못 됨
addTodo: function() {
if(this.newTodoItem !== '') {
this.$emit('addTodoItem',this.newTodoItem)
this.clearInput();
} else {
}
},
clearInput: function () {
// 단일 책임 원칙
this.newTodoItem = '';
}
}
}
</script>
<style scoped>
input:focus {
outline: none;
}
.inputBox {
background-color: 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;
}
</style>
slot
- 특정 컴포넌트의 일부분을 재정의 할 수 있게 해준다.
- <slot> 태그로 정의하며 해당 영역은 재정의가 가능하다.
- slot 속성으로 영역을 지정하고 재정의하면 된다.
- 기존 틀 안에서 <slot> 태그의 영역만 name 속성을 기준으로 slot 속성으로 끌어와서 재정의하는 것이다.
<template>
<transition name="modal">
<div class="modal-mask">
<div class="modal-wrapper">
<div class="modal-container">
<div class="modal-header">
<slot name="header">
default header
</slot>
</div>
<div class="modal-body">
<slot name="body">
default body
</slot>
</div>
<div class="modal-footer">
<slot name="footer">
default footer
<button class="modal-default-button" @click="$emit('close')">
OK
</button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</template>
// 사용하는 쪽
<template>
<div class="inputBox shadow">
<input type="text" v-model="newTodoItem" v-on:keyup.enter="addTodo">
<!-- v-on:이벤트 = 실행메서드 -->
<span class="addContainer" v-on:click="addTodo">
<i class="fas fa-plus addBtn"></i>
</span>
<Modal v-if="showModal" @close="showModal = false">
<!--
해당 <slot>의 header 이름을 가진 부분을 재정의 한다.
-->
<h3 slot="header">경고!</h3>
</Modal>
</div>
</template>
<script>
import Modal from "./common/Modal.vue";
'Vue.js' 카테고리의 다른 글
10.Transition (0) | 2020.12.18 |
---|---|
8.중급 지식 (0) | 2020.12.17 |
7. 프로젝트 구조의 파악 (0) | 2020.12.17 |
6. Vue 를 위한 기반지식 (0) | 2020.12.17 |
5.HTTP 통신, Axios (0) | 2020.12.17 |