vue.js/vue.js 2

38. <vue-todo> 사용자 경험 개선 | Modal 컴포넌트 등록 | slot

DEV-Front 2022. 7. 31. 22:41
반응형

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

 

모달 컴포넌트 — Vue.js

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

kr.vuejs.org


<AlertModal.vue>

slot은 부모 컴포넌트에서 자식 컴포넌트의 엘리먼트를 지정할때 사용한다.
부모에 따라서 자식의 컴포넌트에 영향을 받을 테니, 컴포넌트 재사용성면에서 좋은 장점을 가진다.
또한 범위 있는 slot을 통해 컴포넌트 내에서도 잘게 쪼개서 재사용이 가능하다.

<template>
    <transition name="modal">
        <div class="modal-mask">
            <div class="modal-wrapper">
                <div class="modal-container">
                    <i class="fa-solid fa-xmark modal-default-button" @click="$emit('close')" style="color: #42b983;"></i>
                    <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">
                            copy right
                            <button class="modal-default-button" @click="$emit('close')">
                                OK
                            </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, .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>

<TodoInput.vue>

할 일 입력 안하고 add 버튼 눌렀을시 경고창 구현

<template>
    <div class="inputBox shadow">
        <input type="text" v-model="newTodoTtem" v-on:keyup.enter="addTodo">
        <span class="addContainer" v-on:click="addTodo">
            <i class="fa-solid fa-plus" style="color:#fff;"></i>
        </span>

        <Modal v-if="showModal" @close="showModal = false">
            <!--
            you can use custom content here to overwrite
            default content
            -->
            <h3 slot="header">경고!</h3>
            <p slot="body">할 일을 입력하세요</p>
        </Modal>
    </div>
</template>

<script>

import Modal from './common/AlertModal.vue'

export default {
    components : {
        Modal
    },
    // data는 함수. 하나의 객체만을 반환
    data: function(){
        return {
            newTodoTtem:"",      
            showModal: false      
        }
    },
    methods: {
        addTodo(){
            if (this.newTodoTtem !== '') { //값이 있을때
               this.$emit('addTodoItem', this.newTodoTtem);              
               this.cleaerInput();          
            }else{
                this.showModal = !this.showModal;
            }
        },
        cleaerInput(){
            this.newTodoTtem='';
        },
    }
};
</script>

<style lang="scss" scoped>

input:focus{
    outline: none;
}
.inputBox{
    background: #fff;
    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: #fff;
    vertical-align: middle;
}
</style>
반응형