02.02(목)-2 : Vue CLI 반응성

하이·2023년 2월 3일
0

수업

목록 보기
20/41
post-custom-banner

App.vue

<template>
  <div id="app">
    <TodoHeader></TodoHeader>
    <TodoInput v-on:addTodoItem="addOneItem"></TodoInput>
    <TodoList v-bind:propsdata="todoItems" v-on:removeItem="removeOneItem"></TodoList>
    <TodoFooter v-on:clearAll="clearAllItems"></TodoFooter>
  </div>
</template>

<script>
import TodoHeader from './components/TodoHeader.vue'
import TodoInput from './components/TodoInput.vue'
import TodoList from './components/TodoList.vue'
import TodoFooter from './components/TodoFooter.vue'

export default {
    components: {
      TodoHeader,
      TodoInput,
      TodoList,
      TodoFooter
    },
    data() {  // TodoList.vue에서 옮김
        return {
            todoItems: []
        }
    },
    
  methods: {
    addOneItem(todoItem) {
      let obj = {completed: false, item: todoItem};
      localStorage.setItem(todoItem, todoItem);
      this.todoItems.push(todoItem);
    },
    removeOneItem(todoItem, index) {
      this.todoItems.splice(index, 1);
      localStorage.removeItem(todoItem);   
      console.log("aaa");
    },
    
    // toggleOneItem(todoItem, index) {
    //   // todoItem.completed = !todoItem.completed;
    //   // this.todoItems[index].completed = !this.todoItems[index].completed;
    //   localStorage.removeItem(todoItem.item);
    //   localStorage.setItem(todoItem.item, todoItem.item);
    // },

    clearAllItems() {
      localStorage.clear();
      this.todoItems = []; //다시 빈 배열로 만들기
    }
  

  },

  created() {
      if (localStorage.length > 0) {
      // localStorage에서 데이터를 가져다가 todoItems에다 넣음
      for(let i=0; i<localStorage.length; i++){
          if(localStorage.key(i) !== 'loglevel:webpack-dev-server'){
              // 데이터 넣기, key(i)로 key값을 가져옴. 몇번째 key값이냐
              this.todoItems.push(localStorage.getItem(localStorage.key(i)));
          }
        } 
      }
    }

};
</script>

<style>
body {
    text-align: center;
    background-color: #F6F6F8;
}

input {
    border-style: groove;
    width: 200px;
}

button {
    border-style: groove;
}

.shadow {
    box-shadow: 5px 10px 10px rgba(0,0,0, 0.03);
}
</style>

TodoHeader.vue

<template>
    <h1> 환영합니다 </h1>
</template>

<script>
export default {
    
}
</script>

<style scoped>
h1 {
  color: #2F3B52;
  font-weight: 900;         /* 텍스트 굵기 */
  margin: 2.5rem 0 1.5rem
}
</style>

TodoList.vue

<template>
    <section>
        <!-- <ul>
            <li v-for="todoItem in todoItems">{{ todoItem }}</li>
        </ul> -->
        <ul>
            <li v-for="(todoItem, index) in propsdata" v-bind:key="todoItem.item" class="shadow">
            <i class="checkBtn fa fa-check" aria-hidden="true" ></i>
            {{ todoItem }}
            <!-- @click은 v-on:click과 동일하게 동작합니다. 
                    추가적으로 @click="[method1(), method2()]" 와 같이 사용하면
                    클릭이벤트를 여러개 설정할 수 있습니다.
                -->

            <!-- 삭제버튼 -->
            <span
                class="removeBtn"
                type="button"
                @click="removeTodo(todoItem, index)"
            >
                <i class="fa fa-trash" aria-hidden="true"></i>
            </span>
            </li>
        </ul>
    </section>
</template>

<script>
export default {
// 반응성을 위해 얘를 App.vue로 이동함    
//    data() {
//         return {
//             todoItems: [],
//         };
//     },
    props: ['propsdata'],
    methods : {
        // removeTodo: function(todoItem, index) {
        //     //localStorage.removeItem(todoItem);
        //     // splice() 함수는 JavaScript 내장함수로
        //     // 특정 인덱스에서 부여한 숫자만큼의 인덱스를
        //     // 삭제합니다.
        //     // 많이 사용하니 기억하는게 좋습니다.
        //     //this.todoItems.splice(index,1);
        //     this.$emit('removeItem', todoItem, index);        
        // },
        removeTodo(todoItem, index) { 
            this.$emit('removeItem', todoItem, index);
        },
    
        // toggleComplete(todoItem, index) {
        //     // todoItem.completed = !todoItem.completed;
        //     // localStorage.removeItem(todoItem.item);
        //     // localStorage.setItem(todoItem.item, JSON.stringify(todoItem));
        //      this.$emit('toggleItem', todoItem, index);
        // },

        // created : function () {
        //     if (localStorage.length > 0) {
        //         // localStorage에서 데이터를 가져다가 todoItems에다 넣음
        //         for(let i=0; i<localStorage.length; i++){
        //             if(localStorage.key(i) !== 'loglevel:webpack-dev-server'){
        //                 // 데이터 넣기, key(i)로 key값을 가져옴. 몇번째 key값이냐
        //                 this.todoItems.push(localStorage.key(i));
        //             }
        //         } 
        //     }      
        // },
    }
   };


</script>

<style scoped>
ul {
  list-style-type: none;
  padding-left: 0px;
  margin-top: 0;
  text-align: left;
}

li {
  display: flex;
  min-height: 50px;
  height: 50px;
  line-height: 50px;
  margin: 0.5rem 0;
  padding: 0 0.9rem;
  background: white;
  border-radius: 5px;
}

.checkBtn {
  line-height: 45px;
  color: #62acde;
  margin-right: 5px;
}

.removeBtn {
  margin-left: auto;
  color: #de4343;
}
</style>

TodoInput.vue

<template>
  <div class="inputBox shadow">
    <!-- enter 눌러도 추가되도록 v-on:keyup.enter -->
    <input
      type="text"
      placeholder="할 일을 입력하세요"
      v-model="newTodoItem"
      v-on:keyup.enter="addTodo"
    />
    <span class="addContainer" v-on:click="addTodo">
      <i class="addBtn fa fa-plus" aria-hidden="true"></i>
    </span>
    <!-- <button @click="addTodo">추가</button> 위의 <span></span>으로 버튼 변경-->
  </div>
</template>

<script>
export default {
  data() {
    return {
      newTodoItem: ""
    };
  },
  methods: {
    addTodo() {
      // 현재 입력한 할 일 목록을 저장해야 함
      // 지금 서버 프로그램에 연결을 할 수 없음
      // 서버쪽 데이터베이스에 해당 정보를 저장할 수 없음
      // 그래서 browser가 가지고 있는 저장 장소를 이용
      // browser내부에 저장장소가 크게 2가지 있음
      // Storage와 IndexedDB가 있음
      // Storage를 사용해 보자
      // Storage는 LocalStorage와 SessionStorage로 나뉨
      // 가장 일반적인 LocalStorage를 이용해보자
      // JavaScript를 이용해서 이 저장공간에 내가 원하는 데이터 저장 가능
      // 데이터는 Map 형태로 저장 가능 (key,value의 쌍)
      // 여러 프로그램에 의해 데이터가 중복되는걸 방지하기위해
      // 각 데이터는 domain으로 구분되어서 저장 !

      // localStorage에 데이터 저장하기
      // localStorage.setItem('키값', '변수값');
      if (this.newTodoItem !== "") {
        // var obj = {completed: false, item: this.newTodoItem}; // 클릭 boolean 저장
        // localStorage.setItem(this.newTodoItem, this.newTodoItem);
        // localStorage.setItem(this.newTodoItem, JSON.stringify(obj));

        // 이 키워드 사용하면 이 공간을 내가 이용할 수 있어!
        // localStorage.setItem('키값','변수값')
       
       // this.$emit('이벤트 이름', 인자1, 인자2, ...);
       this.$emit('addTodoItem', this.newTodoItem)
       // 비워주기(초기화)
       this.clearInput();
       //this.newTodoItem = "";
      }
      console.log("클릭클릭");
    },
    
    clearInput: function() {
      this.newTodoItem= ''; //비워주기(초기화)
    }
  }
};
</script>

<style scoped>
input:focus {
  outline: none;
}
.inputBox {
  background: 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: inline-block;
  width: 3rem;
  border-radius: 0 5px 5px 0;
}
.addBtn {
  color: white;
  vertical-align: middle;
}
</style>

TodoFooter.vue

<template>
    <div class="clearAllContainer">
    <span class="clearAllBtn" @click="clearTodo">모두 삭제</span>
  </div>
</template>

<script>
export default {
    methods: {
        clearTodo(){
            // localStorage.clear();
            this.$emit('clearAll');
        }
    }
}
</script>

<style scoped>
.clearAllContainer {
  width: 8.5rem;
  height: 50px;
  line-height: 50px;
  background-color: white;
  border-radius: 5px;
  margin: 0 auto;
}

.clearAllBtn {
  color: #e20303;
  display: block;
}
</style>
profile
기록의 즐거움 😆💻
post-custom-banner

0개의 댓글