본문 바로가기
개발/React

[vue] vue 모달창, 다이얼로그 기능 구현하기(ft. slot)

by 코딩하는 갓디노 2020. 11. 23.

vue.js 가이드를 활용하여
모달창을 구현하겠습니다.



 


참고문서

vuejs.org/v2/examples/modal.html

 

Modal Component — Vue.js

Vue.js - The Progressive JavaScript Framework

vuejs.org

위의 링크로 이동하여, html과 css의 코드를 그대로 나의 문서에 적용시키면 됩니다. 

 

모달창 적용 방법

1. Modal.vue 의 파일(모달용 하위 컴포넌트)을 하나 생성합니다.
2. 상위 컴포넌트에 Modal 컴포넌트를 부릅니다.(import)
3. 가이드의 코드를 위의 컴포넌트들에게 적용합니다. 

 

구현 화면

 

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')">
                close
              </button>
            </slot>
          </div>
        </div>
      </div>
    </div>
  </transition>
</template>

<script>
export default {};
</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;
}
.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);
}
.modal-body,
.modal {
  color: #666 !important;
}
</style>



 


TodoInput.vue(상위 컴포넌트)

<template>
  <div>
    <div class="md-layout" style="margin: 0.5rem; color: #fff !important">
      <div class="md-layout-item md-size-90">
        <md-field>
          <label>Things To Do</label>
          <md-input v-model="doItem" @keyup.enter="addTodo"></md-input>
        </md-field>
      </div>
      <div class="md-layout-item md-size-10" @click="addTodo">
        <i class="fas fa-plus-circle addBtn"></i>
      </div>

      <Modal v-if="showModal" @close="showModal = false">
        <h3 slot="header">
          알림!
          <i class="fas fa-times closeModalBtn" @click="showModal = false"></i>
        </h3>
        <div slot="body">할일을 입력하세요.</div>
      </Modal>
    </div>
  </div>
</template>

<script>
import Modal from "./common/Modal";
export default {
  components: {
    Modal,
  },
  data: function () {
    return {
      doItem: "",
      showModal: false,
    };
  },
  methods: {
    addTodo() {
      if (this.doItem) {
        // this.$emit('이벤트이름', 인자1, 인자2);
        this.$emit("addOne", this.doItem);
        this.clearInput();
      } else {
        this.showModal = !this.showModal;
      }
    },
    clearInput() {
      this.doItem = "";
    },
  },
};
</script>

<style>
.md-field,
.md-focused,
.md-input,
.md-textarea,
label {
  background: #365fd9 !important;
  border-style: none;
  border-radius: 5px;
  margin: 0 0 5px 0 !important;
  color: #fff !important;
  -webkit-text-fill-color: #ddd !important;
}
.addBtn {
  vertical-align: middle;
  margin-top: 12px;
  font-size: 24px;
  cursor: pointer;
}
.closeModalBtn {
  color: #42b983;
}
</style>

 

slot 태그

여기서 중요한 것은 slot 태그입니다. 

하위 모달 컴포넌트에서 <slot name="header"> </slot>로 
header라는 이름의 slot을 정의합니다. 

상위 컴포넌트에서 div, template, span 등의 태그 안에
slot="header" 으로 slot을 불러올 수 있습니다. 
slot을 불러온 태그 안에 컨텐츠가 화면에 출력됩니다. 

즉, 화면에 보여질 데이터는 상위 컴포넌트에서  설정되고,
하위 모달 컴포넌트에서는 slot 태그를 이용하여 틀만 정의 합니다. 

반응형

댓글