본문 바로가기
Dev/Vue.js

[Vue.js] Todo App 사용자 경험 개선하기

by dev_jsk 2020. 9. 10.
728x90
반응형

개선사항

입력란 빈 값일 때 추가 시 확인 알람(모달 컴포넌트 등록), 트랜지션 구현

모달 컴포넌트 등록

구조 및 코드

// 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 {};
</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 {
  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>

참고

vuejs.org/v2/examples/modal.html

 

Modal Component — Vue.js

Vue.js - The Progressive JavaScript Framework

vuejs.org

TodoInput에 등록

기능

  • 빈 값으로 추가 시 Modal창으로 경고 출력
// TodoInput.vue

<template>
  <div class="inputBox shadow">
    <input type="text" v-model="newTodoItem" v-on:keyup.enter="addTodo" />
    <span class="addContainer" v-on:click="addTodo">
      <i class="fas fa-plus addBtn"></i>
    </span>
    <!-- Modal 등록 -->
    <Modal v-if="showModal" @close="showModal=false">
      <h3 slot="header">
        경고 !
        <!-- v-on:click => @click ES6 문법 -->
        <i class="closeModalBtn fas fa-times" @click="showModal = false"></i>
      </h3>
      <div slot="body">값을 입력하세요.</div>
    </Modal>
  </div>
</template>

<script>
import Modal from "./common/Modal.vue";

export default {
  data: function () {
    return {
      newTodoItem: "",
      showModal: false,
    };
  },
  methods: {
    addTodo: function () {
      if (this.newTodoItem !== "") {
        this.$emit("addTodoItem", this.newTodoItem);
        this.clearInput();
      } else {
        // 빈 값일 경우 Modal창 표시
        this.showModal = !this.showModal;
      }
    },
    clearInput: function () {
      this.newTodoItem = "";
    },
  },
  components: {
    Modal: Modal,
  },
};
</script>

<style scoped>
...
.closeMdoalBtn {
  color: #42b983;
}
</style>

slot

특정 컴포넌트에서 다른 컴포넌트를 등록하여 사용 시 웹 컴포넌트 사용자가 자신만의 마크업으로 채워 별도의 DOM 트리를 생성하고, 컴포넌트와 함께 표현할 수 있는 웹 컴포넌트 내부의 플레이스홀더

Transitions

CSS 프로퍼티의 값이 변화할 때, 프로퍼티 값의 변화가 일정 시간(duration)에 걸쳐 일어나도록 하는 것으로 Vue.js에서는 CSS Transition효과를 더 빠르고 간단하게 구현하기 위해 컴포넌트(태그)를 제공한다.

 

진입/진출 트랜지션 클래스

  • v-enter : enter의 시작 상태. 요소가 삽입되기 전에 적용되고 한 프레임 후에 제거
  • v-enter-active : enter에 대한 활성 및 종료 상태. 요소가 삽입되기 전에 적용되고 트랜지션/애니메이션이 완료되면 제거
  • v-enter-to : (2.1.8 이상 버전에서 지원)진입 상태의 끝에서 실행. 요소가 삽입된 후 (동시에 v-enter가 제거), 트랜지션/애니메이션이 끝나면 제거
  • v-leave : leave를 위한 시작 상태. 진출 트랜지션이 트리거 될 때 적용되고 한 프레임 후에 제거
  • v-leave-active : leave에 대한 활성 및 종료 상태. 진출 트랜지션이 트리거되면 적용되고 트랜지션/애니메이션이 완료되면 제거
  • v-leave-to : (2.1.8 이상 버전에서 지원)진출 상태의 끝에서 실행. 진출 트랜지션이 트리거되고 (동시에 v-leave가 제거), 트랜지션/애니메이션이 끝나면 제거

TodoList에 구현

기능

  • 할 일 추가, 삭제 시 리스트 공간에 애니메이션 동작
// TodoList.vue

<template>
  <div>
    <!-- transition : 하나의 요소, transition-group : 여러 요소 -->
    <transition-group name="list" tag="ul">
      <li v-for="(todoItem, index) in propsdata" v-bind:key="todoItem.item" class="shadow">
        <i
          class="checkBtn fas fa-check"
          v-bind:class="{checkBtnCompleted: todoItem.completed}"
          v-on:click="toggleComplete(todoItem, index)"
        ></i>
        <span v-bind:class="{textCompleted: todoItem.completed}">{{ todoItem.item }}</span>
        <span class="removeBtn" v-on:click="removeTodo(todoItem, index)">
          <i class="fas fa-trash"></i>
        </span>
      </li>
    </transition-group>
  </div>
</template>

<script>
export default {
  ...
};
</script>

<style scoped>
...
/* 리스트 아이템 트렌지션 효과 */
.list-enter-active,
.list-leave-active {
  transition: all 1s;
}
.list-enter,
.list-leave-to {
  opacity: 0;
  transform: translateY(30px);
}
</style>

참고

vuejs.org/v2/guide/transitions.html

 

Enter/Leave & List Transitions — Vue.js

Vue.js - The Progressive JavaScript Framework

vuejs.org

728x90
반응형

'Dev > Vue.js' 카테고리의 다른 글

[Vue.js] Vuex  (0) 2020.09.11
[Vue.js] ES6  (0) 2020.09.11
[Vue.js] Todo App 개선하기  (0) 2020.09.10
[Vue.js] Todo App 만들기  (0) 2020.09.10
[Vue.js] 싱글 파일 컴포넌트  (0) 2020.09.09

댓글