Vue.js

9.Modal

Jungsoomin :) 2020. 12. 18. 13:19

VueReact 와 대비해 가지는 장점은 라이브러리 단에서 애니매이션과 트랜지션 등을 지원하는 것이다.

 

kr.vuejs.org/v2/examples/modal.html

 

모달 컴포넌트 — Vue.js

Vue.js - 프로그레시브 자바스크립트 프레임워크

kr.vuejs.org

 


  • .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