[Vue.js] todoList 만들기1_3. 컴포넌트 나누기_작성중

2021. 7. 4. 17:13프로젝트/ToDoList

728x90

 

 

 

 

 

 

 

현재까지 구현기능

- 할 일 입력시 리스트에 추가

- 리스트에서 우측 'x'버튼 클릭시 삭제

- 리스트 하단 총 개수 표시

- 리스트 하단 '전체,해야할일,완료할일' 버튼 클릭시 각 상태별 리스트 표시

- localStorage와 값을 연동하여, 새로고침시에도 값이 유지되어 표현됨

* 위 내용들은 현재 블로그에 작성 못함.. 

 

 

추가로 구현해야할 기능

- TodoList.vue에 한번에 작성된 상태 컴포넌트별로 나눠서 구현 필요

   -> 나눠서 구현 이후 Vuex적용 해보기

- 개발자도구에서  localStorage값을 전체 삭제시 Vue에서 인지 못함(새로고침시에만 적용됨) 

 

 

기존 프로젝트는 TodoList.vue에 한번에 작성

-> 변경 프로젝트는 TodoInput.vue, TodoList.vue, TodoStatus.vue 총 3개의 컴포넌트로 나눠서 적용해보기

 

 

 

 

 

 


[ 변경전 ]

 

App.vue

<template>
<div>
  <TodoList></TodoList>
</div>
</template>

<script>
 import TodoList from './components/TodoList.vue';

export default { 
  name: 'App',
  components: {
    TodoList
  }
}
</script>

<style>
</style>

 

TodoList.vue

<!--기존 TodoList.vue만 사용 -> TodoInput.vue, TodoList.vue, TodoStatus.vue 총 3개의 컴포넌트로 나눠서 적용해보기 -->
<!--localStorage 값형태 json object형식으로 변경 -->
<!--localStorage내부 completed는 변경 안하고 dynamicLists에 completed만 변경하고 있음 그래서 새로고침시 다 false -->
<template>
   <div class="todoapp">
      <h1>TODOS</h1>
      <input
        id="new-todo-title"
        class="new-todo"
        placeholder="할일을 추가해주세요"
        autofocus
        @keyup.enter="enterKeyFunction"
        v-model="todoInput"
      />
      <ul id="todo-list" class="todo-list" v-if="showTodoList"> 
          <li v-for="(list, index) in dynamicLists[0]" :key="index" v-bind:class="{completed : isCompletedArr[index] === true, hidden : isHidden[index]}">
            <div class="view">
            <input class="toggle" type="checkbox" @change="toggleCompleted(index)" v-model="isCompletedArr[index]"  value="index"/>
            <label class="label">{{list.item}}</label>
            <button class="destroy" @click="toggleDestroyed(index)"></button> 
            </div>
            <input class="edit" value="새로운 타이틀" />
        </li>
      </ul>
      <main>
        <input class="toggle-all" type="checkbox" v-model="completedChecked"/>
        <ul id="todo-list" class="todo-list"></ul>
        <div class="count-container">
          <span class="todo-count">총 <strong id="todoItemTotCnt">{{totalCount}}</strong> 개</span>
          <ul class="filters" id="filtersGroup">
            <li>
              <a v-bind:class="{all, filterBtn, selected:isSelected[0]}" href="#" id="allBtn" @click="toggleFiltered('all')">전체보기</a>
            </li>
            <li>
              <a v-bind:class="{active, filterBtn, selected:isSelected[1]}" href="#active" @click="toggleFiltered('active')">해야할 일</a>
            </li>
            <li>
              <a v-bind:class="{completed, filterBtn, selected:isSelected[2]}" href="#completed" @click="toggleFiltered('completed')">완료한 일</a>
            </li>
          </ul>
        </div>
      </main>
    </div>
</template>

<script>
//import DynamicList from './DynamicList.vue';
export default {
    // components:{
    //     DynamicList
    // },
    data(){
        return {
            todoInput :'',  
            dynamicLists:[{}],
            completedChecked:[],
            isShowTodoList:false,
            isCompletedArr:{},
            isHidden:{},
            isSelected:[true],
            totalCount:0,
            toggleStatus:'',
            localStorageLength:0,
            now:"0000년00월00일00시00분00초", //입력시간세팅
        }
    },
    created(){
        let totCnt = 0;
        this.localStorageLength = localStorage.length
        for(let i=0; i<this.localStorageLength; i++){
            if(localStorage.key(i).indexOf('loglevel:') === -1){
             this.dynamicLists[0][localStorage.key(i)] = JSON.parse(localStorage.getItem(localStorage.key(i)));
             if( this.dynamicLists[0][localStorage.key(i)].completed){
                 this.isCompletedArr[localStorage.key(i)] = true;
             }
             totCnt++;
            }
        }
        this.totalCount = totCnt;
    },
    computed:{

    },
    methods:{
        getCurrTime(){
            let date = new Date();
            this.now = `${date.getFullYear()}년 ${date.getMonth()+1}월 ${date.getDate()}일 ${date.getHours()}시 ${date.getMinutes()}분 ${date.getSeconds()}초 `;
                      
        },
        enterKeyFunction(){
            this.getCurrTime();
            if(this.todoInput.trim()!=="" && !localStorage.getItem(this.todoInput) ){
            let value ={
                        item:this.todoInput
                        ,completed:false
                        ,time:this.now
            };
             localStorage.setItem(this.todoInput,JSON.stringify(value));
             this.dynamicLists[0][this.todoInput] = JSON.parse(localStorage.getItem(this.todoInput));
            //  localStorage.setItem(this.todoInput,this.todoInput);
            //  this.dynamicLists.push(localStorage.getItem(this.todoInput));
            }
            console.log(this.dynamicLists[0])
            console.log(this.dynamicLists)
            this.todoInput = '';
            this.isNotHiddenCnt();
        },
        showTodoList(){
            if(this.dynamicLists.length > 0){
                this.isShowTodoList = true;
            }else{
                this.isShowTodoList = false;
            }
            return this.isShowTodoList;
        },
        toggleCompleted(idx){
              if(!this.isCompletedArr[idx]){
                  localStorage.removeItem(idx);
                   let value = {
                        item:this.dynamicLists[0][idx].item
                        ,completed:false
                        ,time:this.dynamicLists[0][idx].time
                    };
                  localStorage.setItem(idx,JSON.stringify(value));
                  this.dynamicLists[0][idx].completed = false
              } else{
                   localStorage.removeItem(idx);
                   let value = {
                        item:this.dynamicLists[0][idx].item
                        ,completed:true
                        ,time:this.dynamicLists[0][idx].time
                    };
                  localStorage.setItem(idx,JSON.stringify(value));
                  this.dynamicLists[0][idx].completed = true
              }
            //  if(this.isCompletedArr[idx]){
            //      this.isCompleted = true;
            //  }else{
            //      this.isCompleted = false;
            //  }
            this.toggleFiltered(this.toggleStatus);
        },
        toggleDestroyed(idx){
            delete this.dynamicLists[0][idx];
            localStorage.removeItem(idx);
            
        },
        toggleFiltered(status){
            let dynamicListKeys = Object.keys(this.dynamicLists[0]);
            this.toggleStatus = status;
            for(let i=0; i<dynamicListKeys.length; i++){             
                this.isHidden[dynamicListKeys[i]]=false;
                this.isSelected.splice(0,0,true);
                this.isSelected.splice(1,0,false);
                this.isSelected.splice(2,0,false);
                if(this.toggleStatus  === 'active'){
                    this.isSelected.splice(0,0,false);
                    this.isSelected.splice(1,0,true);
                    this.isSelected.splice(2,0,false);
                     if(this.dynamicLists[0][dynamicListKeys[i]].completed){
                         console.log(dynamicListKeys[i]);
                        this.isHidden[dynamicListKeys[i]]=true
                    }
                 }
                 else if(this.toggleStatus === 'completed'){
                    this.isSelected.splice(0,0,false);
                    this.isSelected.splice(1,0,false);
                    this.isSelected.splice(2,0,true);
                     if(!this.dynamicLists[0][dynamicListKeys[i]].completed){
                        this.isHidden[dynamicListKeys[i]]=true
                    }
                 }
                }

            // if(this.toggleStatus  === 'active'){
            //     for(let i=0; i< dynamicListKeys.length; i++){
            //         if(this.isHidden[dynamicListKeys[i]]){
            //             this.isHidden[dynamicListKeys[i]]=true
            //         }
            //     }
            // } else if(this.toggleStatus  === 'completed'){
            //      for(let i=0; i< dynamicListKeys.length; i++){
            //         if(!this.isHidden[dynamicListKeys[i]]){
            //             this.isHidden[dynamicListKeys[i]]=true
            //         }
            //     }
            // }
            this.isNotHiddenCnt();
        },
         isNotHiddenCnt(){
            let hiddenCnt = 0 ;
            const isHiddenLength = Object.keys(this.isHidden).length;
            const todoListLength = Object.keys(this.dynamicLists[0]).length;
            for(let i=0; i<isHiddenLength; i++){
                if(this.isHidden[Object.keys(this.dynamicLists[0])[i]]){
                    hiddenCnt++;
                }
            }
            this.totalCount = todoListLength - hiddenCnt;
            return this.totalCount;
        }
    }
}
</script>

<style scoped>
html,
body {
    margin: 0;
    padding: 10px;
}

button {
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    font-size: 100%;
    vertical-align: baseline;
    font-family: inherit;
    font-weight: inherit;
    color: inherit;
    -webkit-appearance: none;
    appearance: none;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

body {
    font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
    line-height: 1.4em;
    background: #f5f5f5;
    color: #4d4d4d;
    min-width: 230px;
    max-width: 550px;
    margin: 0 auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-weight: 300;
}

:focus {
    outline: 0;
}

.hidden {
    display: none;
}

.todoapp {
    background: #fff;
    margin: 130px 0 40px 0;
    position: relative;
    box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
    0 25px 50px 0 rgba(0, 0, 0, 0.1);
}

.todoapp input::-webkit-input-placeholder {
    font-style: italic;
    font-weight: 300;
    color: #e6e6e6;
}

.todoapp h1 {
    position: absolute;
    top: -125px;
    width: 100%;
    font-size: 60px;
    text-align: center;
    color: dimgray;
    font-weight: 100;
    font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
}

.new-todo,
.edit {
    position: relative;
    margin: 0;
    width: 100%;
    font-size: 24px;
    font-family: inherit;
    font-weight: inherit;
    line-height: 1.4em;
    border: 0;
    color: inherit;
    padding: 6px;
    box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.new-todo {
    padding: 16px 16px 16px 60px;
    border: none;
    background: rgba(0, 0, 0, 0.003);
    box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
}

main {
    position: relative;
    z-index: 2;
    border-top: 1px solid #e6e6e6;
}

.toggle-all {
    width: 1px;
    height: 1px;
    border: none;
    opacity: 0;
    position: absolute;
    right: 100%;
    bottom: 100%;
}

.toggle-all + label {
    width: 60px;
    height: 34px;
    font-size: 0;
    position: absolute;
    top: -52px;
    left: -13px;
    -webkit-transform: rotate(90deg);
    transform: rotate(90deg);
}

.toggle-all + label:before {
    content: '❯';
    font-size: 22px;
    color: #e6e6e6;
    padding: 10px 27px 10px 27px;
}

.toggle-all:checked + label:before {
    color: #737373;
}

.todo-list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.todo-list li {
    position: relative;
    font-size: 24px;
    border-bottom: 1px solid #ededed;
}

.todo-list li:last-child {
    border-bottom: none;
}

.todo-list li.editing {
    border-bottom: none;
    padding: 0;
}

.todo-list li.editing .edit {
    display: block;
    width: calc(100% - 43px);
    padding: 12px 16px;
    margin: 0 0 0 43px;
}

.todo-list li.editing .view {
    display: none;
}

.todo-list li .toggle {
    text-align: center;
    width: 40px;
    height: auto;
    position: absolute;
    top: 0;
    bottom: 0;
    margin: auto 0;
    border: none;
    -webkit-appearance: none;
    appearance: none;
}

.todo-list li .toggle {
    opacity: 0;
}

.todo-list li .toggle + label {
    background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
    background-repeat: no-repeat;
    background-position: center left;
}

.todo-list li .toggle:checked + label {
    background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
}

.todo-list li label {
    word-break: break-all;
    padding: 15px 15px 15px 60px;
    display: block;
    line-height: 1.2;
    transition: color 0.4s;
}

.todo-list li.completed label {
    color: #d9d9d9;
    text-decoration: line-through;
}

.todo-list li .destroy {
    display: none;
    position: absolute;
    top: 0;
    right: 10px;
    bottom: 0;
    width: 40px;
    height: 40px;
    margin: auto 0;
    font-size: 30px;
    color: #cc9a9a;
    margin-bottom: 11px;
    transition: color 0.2s ease-out;
    cursor: pointer;
}

.todo-list li .destroy:hover {
    color: #af5b5e;
}

.todo-list li .destroy:after {
    content: '×';
}

.todo-list li:hover .destroy {
    display: block;
}

.todo-list li .edit {
    display: none;
}

.todo-list li.editing:last-child {
    margin-bottom: -1px;
}

.count-container {
    color: #777;
    padding: 10px 15px;
    height: 20px;
    text-align: center;
    border-top: 1px solid #e6e6e6;
}

.count-container:before {
    content: '';
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 50px;
    overflow: hidden;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
    0 8px 0 -3px #f6f6f6,
    0 9px 1px -3px rgba(0, 0, 0, 0.2),
    0 16px 0 -6px #f6f6f6,
    0 17px 2px -6px rgba(0, 0, 0, 0.2);
}

.todo-count {
    float: left;
    text-align: left;
}

.todo-count strong {
    font-weight: 300;
}

.filters {
    margin: 0;
    padding: 0;
    list-style: none;
    position: absolute;
    right: 0;
    left: 0;
}

.filters li {
    display: inline;
}

.filters li a {
    color: inherit;
    margin: 3px;
    padding: 3px 7px;
    text-decoration: none;
    border: 1px solid transparent;
    border-radius: 3px;
}

.filters li a:hover {
    border-color: rgba(175, 47, 47, 0.1);
}

.filters li a.selected {
    border-color: rgba(175, 47, 47, 0.2);
}

.clear-completed, html .clear-completed:active {
    float: right;
    position: relative;
    line-height: 20px;
    text-decoration: none;
    cursor: pointer;
}

.clear-completed:hover {
    text-decoration: underline;
}

.info {
    margin: 65px auto 0;
    color: #bfbfbf;
    font-size: 10px;
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
    text-align: center;
}

.info p {
    line-height: 1;
}

.info a {
    color: inherit;
    text-decoration: none;
    font-weight: 400;
}

.info a:hover {
    text-decoration: underline;
}

</style>

 

 


[ 변경 1 . TodoInpurt.vue ]

1. TodoInput.vue 생성 후 App.vue에 추가

 

App.vue

<template>
<div>
  <TodoInput></TodoInput>
  <TodoList></TodoList>
</div>
</template>

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

export default { 
  name: 'App',
  components: {
    TodoInput
    ,TodoList
  }
}
</script>

<style>
</style>

 

 

2. 할 일을 입력하는 항목은 TodoInput.vue , 리스트를 표시하는 항목은 TodoList.vue로 분리 

 

기존에 TodoList.vue 한 페이지 내에서 입력하고 입력한 내용이 조회되었는데, 입력하는 "#new-todo-title" input박스를 TodoInput.vue로 분리시킨 뒤, 할 일을 입력 후 리스트에 추가하는 함수인 enterKyFunction을 실행시 입력된 값(v-model=todoInput)을 형제컴포넌트인 TodoList.vue로 넘겨받도록 하여 리스트에 추가하도록 변경.

*여기서 원래 eventBus를 사용하여 형제컴포넌트로 값을 전달하려고 하였으나, Vue3부터는 $on이벤트를 사용할 수 없다고 하여 mitt(설명클릭)이라는 외부라이브러리를 사용하여 데이터를 이동시킴.

 

TodoInput.vue

<template>
    <div class="todoapp">
      <h1>TODOS</h1>
      <input
        id="new-todo-title"
        class="new-todo"
        placeholder="할일을 추가해주세요"
        autofocus
        @keyup.enter="enterKeyFunction"
        v-model="todoInput"
      />
    </div>
</template>

<script>
export default {
    data(){
        return{
            todoInput :'',
        }
    },
    methods:{
        enterKeyFunction(){
            this.emitter.emit('addTodoInput', this.todoInput)
            this.todoInput = '';
        }
    }
}
</script>

- 할일을 입력하면 v-model에 정의된 todoInput으로 값이 매핑됨.

- 입력을 마치고 엔터를 클릭시 @keyup.enter를 통해 enterKeyFunction을 호출

- enterKeyFunction()에 정의된 대로 this.emitter.emit('addTodoInput', this.todoInput)을 통해 'addTodoInput'이라는 이벤트 이름으로 this.todoInput을 파라미터로 보냄

- 이벤트 보낸 후 새로운 입력을 위해 this.todoInput 초기화('')

 

TodoList.vue

<template>
   <div class="todoapp">
      <ul id="todo-list" class="todo-list" v-if="showTodoList"> 
          <li v-for="(list, index) in dynamicLists[0]" :key="index" v-bind:class="{completed : isCompletedArr[index] === true, hidden : isHidden[index]}">
            <div class="view">
            <input class="toggle" type="checkbox" @change="toggleCompleted(index)" v-model="isCompletedArr[index]"  value="index"/>
            <label class="label">{{list.item}}</label>
            <button class="destroy" @click="toggleDestroyed(index)"></button> 
            </div>
            <input class="edit" value="새로운 타이틀" />
        </li>
      </ul>
      <main>
        <input class="toggle-all" type="checkbox" v-model="completedChecked"/>
        <ul id="todo-list" class="todo-list"></ul>
        <div class="count-container">
          <span class="todo-count">총 <strong id="todoItemTotCnt">{{totalCount}}</strong> 개</span>
          <ul class="filters" id="filtersGroup">
            <li>
              <a v-bind:class="{all, filterBtn, selected:isSelected[0]}" href="#" id="allBtn" @click="toggleFiltered('all')">전체보기</a>
            </li>
            <li>
              <a v-bind:class="{active, filterBtn, selected:isSelected[1]}" href="#active" @click="toggleFiltered('active')">해야할 일</a>
            </li>
            <li>
              <a v-bind:class="{completed, filterBtn, selected:isSelected[2]}" href="#completed" @click="toggleFiltered('completed')">완료한 일</a>
            </li>
          </ul>
        </div>
      </main>
    </div>
</template>

<script>
export default {
    data(){
        return {
            dynamicLists:[{}],
            completedChecked:[],
            isShowTodoList:false,
            isCompletedArr:{},
            isHidden:{},
            isSelected:[true],
            totalCount:0,
            toggleStatus:'',
            localStorageLength:0,
            now:"0000년00월00일00시00분00초", //입력시간세팅
        }
    },
    created(){
        let totCnt = 0;
        this.localStorageLength = localStorage.length
        for(let i=0; i<this.localStorageLength; i++){
            if(localStorage.key(i).indexOf('loglevel:') === -1){
             this.dynamicLists[0][localStorage.key(i)] = JSON.parse(localStorage.getItem(localStorage.key(i)));
             if( this.dynamicLists[0][localStorage.key(i)].completed){
                 this.isCompletedArr[localStorage.key(i)] = true;
             }
             totCnt++;
            }
        }
        this.totalCount = totCnt;
    },
    mounted(){
        this.emitter.on('addTodoInput',this.addTodoInputFunction)
    },
    computed:{

    },
    methods:{
        getCurrTime(){
         let date = new Date();
         this.now = `${date.getFullYear()}년 ${date.getMonth()+1}월 ${date.getDate()}일 ${date.getHours()}시 ${date.getMinutes()}분 ${date.getSeconds()}초 `;
        },
        addTodoInputFunction(todoInput){
            this.getCurrTime();
            if(todoInput.trim()!=="" && !localStorage.getItem(todoInput) ){
            let value ={
                        item:todoInput
                        ,completed:false
                        ,time:this.now
            };
             localStorage.setItem(todoInput,JSON.stringify(value));
             this.dynamicLists[0][todoInput] = JSON.parse(localStorage.getItem(todoInput));
            }
        },
        showTodoList(){
            if(this.dynamicLists.length > 0){
                this.isShowTodoList = true;
            }else{
                this.isShowTodoList = false;
            }
            return this.isShowTodoList;
        },
        toggleCompleted(idx){
              if(!this.isCompletedArr[idx]){
                  localStorage.removeItem(idx);
                   let value = {
                        item:this.dynamicLists[0][idx].item
                        ,completed:false
                        ,time:this.dynamicLists[0][idx].time
                    };
                  localStorage.setItem(idx,JSON.stringify(value));
                  this.dynamicLists[0][idx].completed = false
              } else{
                   localStorage.removeItem(idx);
                   let value = {
                        item:this.dynamicLists[0][idx].item
                        ,completed:true
                        ,time:this.dynamicLists[0][idx].time
                    };
                  localStorage.setItem(idx,JSON.stringify(value));
                  this.dynamicLists[0][idx].completed = true
              }
            this.toggleFiltered(this.toggleStatus);
        },
        toggleDestroyed(idx){
            delete this.dynamicLists[0][idx];
            localStorage.removeItem(idx);
            
        },
        toggleFiltered(status){
            let dynamicListKeys = Object.keys(this.dynamicLists[0]);
            this.toggleStatus = status;
            for(let i=0; i<dynamicListKeys.length; i++){             
                this.isHidden[dynamicListKeys[i]]=false;
                this.isSelected.splice(0,0,true);
                this.isSelected.splice(1,0,false);
                this.isSelected.splice(2,0,false);
                if(this.toggleStatus  === 'active'){
                    this.isSelected.splice(0,0,false);
                    this.isSelected.splice(1,0,true);
                    this.isSelected.splice(2,0,false);
                     if(this.dynamicLists[0][dynamicListKeys[i]].completed){
                         console.log(dynamicListKeys[i]);
                        this.isHidden[dynamicListKeys[i]]=true
                    }
                 }
                 else if(this.toggleStatus === 'completed'){
                    this.isSelected.splice(0,0,false);
                    this.isSelected.splice(1,0,false);
                    this.isSelected.splice(2,0,true);
                     if(!this.dynamicLists[0][dynamicListKeys[i]].completed){
                        this.isHidden[dynamicListKeys[i]]=true
                    }
                 }
                }
            this.isNotHiddenCnt();
        },
         isNotHiddenCnt(){
            let hiddenCnt = 0 ;
            const isHiddenLength = Object.keys(this.isHidden).length;
            const todoListLength = Object.keys(this.dynamicLists[0]).length;
            for(let i=0; i<isHiddenLength; i++){
                if(this.isHidden[Object.keys(this.dynamicLists[0])[i]]){
                    hiddenCnt++;
                }
            }
            this.totalCount = todoListLength - hiddenCnt;
            return this.totalCount;
        }
    }
}
</script>

- TodoList.vue의 mounted()시점에 this.emitter.on('addTodoInput', this.addTodoInputFunction)에서 'addToInput'이라는 이벤트가 발생하면 'this.addTodoFunction'메서드를 실행..?

- addTodoInputFunction(todoInput)에서 TodoInput.vue에서 입력한 값이 todoInput이라는 파라미터로 넘어오고 해당 값을 리스트에 추가(localStorage, dynamicLists에 추가)

 

 

 

 

 

 

 

* 전체적인 프로젝트 진행방향은 블랙커피스터디9기를 참여하여 미션내용과 동일하게 진행하되 Vue.js로 구현하였습니다.

 

NEXTSTEP

 

edu.nextstep.camp

 

 

 

728x90