각각의 컴포넌트에서만 사용할 수 있는 뷰 데이터 속성(newTodoItem, todoItems)
을 갖고 있다.
만약 모든 컴포넌트가 '같은 데이터 속성'
을 조작한다면 화면을 매번 새로 고침해야 하는 문제점을 해결할 수 있다.
같은 데이터 속성을 사용하기 위해 최상위(루트) 컴포넌트인 App
컴포넌트에 todoItems라는 데이터를 정의하고(App을 컨테이너처럼 생각하자), 하위 컴포넌트 TodoList
에 props
로 전달한다.
App.vue가 생성되자 마자 배열을 담을 수 있도록
TodoList.vue
-> App.vue
로 옮김
App.vue
<template>
<div id="app">
...생략...
<!-- <TodoList v-bind:내려보낼 프롭스 속성이름="현재 위치의 컴포넌트 데이터 속성"></TodoList> -->
<TodoList v-bind:propsdata="todoItems"></TodoList>
</div>
</template>
<script>
export default {
data: function() { //옮김
return {
todoItems: []
}
},
created: function() { //옮김
if (localStorage.length > 0) {
for (var i = 0; i < localStorage.length; i++) {
if (localStorage.key(i) !== 'loglevel:webpack-dev-server') {
this.todoItems.push(JSON.parse(localStorage.getItem(localStorage.key(i))));
}
}
}
},
components: {
'TodoHeader': TodoHeader,
'TodoInput': TodoInput,
'TodoList': TodoList,
'TodoFooter': TodoFooter
}
}
</script>
TodoList로 데이터를 내려보내기 위한 propsdata 생성
TodoList.vue
<template>
<section>
<ul>
<li v-for="(todoItem, index) in propsdata" class="shadow" v-bind:key="todoItem.item">
<!-- propsdata로 변경 -->
...생략...
</template>
<script>
export default {
props: ['propsdata'],
methods: {
removeTodo: function(todoItem, index) {
this.todoItems.splice(index, 1);
localStorage.removeItem(todoItem);
},
toggleComplete: function(todoItem) {
todoItem.completed = !todoItem.completed;
localStorage.removeItem(todoItem.item);
localStorage.setItem(todoItem.item, JSON.stringify(todoItem));
}
}
}
</script>
원랜 localhost:8080을 들어갔을 때 localstorage에 들어 있는 내용이 바로 화면에 띄워지지않았다.
하지만 이젠 localhost:8080를 들어가자 마자 항목을 띄운다.
할 일을 추가해도 화면에 바로 띄워지지 않고 새로 고침을 해야하는 문제가 있다.
addOneItem라는 이름으로 method를 하나 생성하고
App.vue
<template>
<div id="app">
...생략...
<!-- <TodoInput v-on:하위 컴포넌트에서 발생시킨 이벤트 이름="현재 컴포넌트에서 메서드 명"></TodoInput> -->
<TodoInput v-on:addTodoItem="addOneItem"></TodoInput>
</div>
</template>
TodoInput.vue
안에 있던 내용을 App.vue
로 옮긴다.
App.vue
<script>
...
export default {
...,
methods: {
addOneItem: function(todoItem) {
var obj = {completed: false, item: todoItem};
localStorage.setItem(todoItem, JSON.stringify(obj));
this.todoItems.push(obj);
}
},
created: function() {
if (localStorage.length > 0) {
for (var i = 0; i < localStorage.length; i++) {
if (localStorage.key(i) !== 'loglevel:webpack-dev-server') {
this.todoItems.push(JSON.parse(localStorage.getItem(localStorage.key(i))));
}
}
}
},
...
}
</script>
맨 위 코드에서 하위 컴포넌트에서 발생시킨 이벤트 이름
을 addTodoItem
이라고 명명했으니
TodoInput.vue
의 메서드 내용을 다음과 같이 매칭한다.
TodoInput.vue
<script>
export default {
...,
methods: {
addTodo: function() {
if (this.newTodoItem !== '') {
// this.$emit('이벤트 이름', 인자1, 인자2, ...);
this.$emit('addTodoItem', this.newTodoItem)
this.clearInput();
}
},
...
}
}
</script>
이제 새로운 항목을 추가하는 버튼을 누르면 새로 고침하지 않아도 바로 화면에 뜬다.
App.vue
<template>
<div id="app">
...
<TodoList v-bind:propsdata="todoItems" v-on:removeItem="removeOneItem"></TodoList>
...
</div>
</template>
<script>
export default {
...,
methods: {
addOneItem: function(todoItem) {
...
},
removeOneItem: function(todoItem, index) {
this.todoItems.splice(index, 1); //특정 index에서 하나를 지울 수 있음
localStorage.removeItem(todoItem.item);
}
},
...
</script>
TodoList.vue
에서 App.vue
로 옮기는 코드
this.todoItems.splice(index, 1); //특정 index에서 하나를 지울 수 있음
localStorage.removeItem(todoItem);
TodoList.vue
<script>
export default {
...,
methods: {
removeTodo: function(todoItem, index) {
this.$emit('removeItem', todoItem, index);
},
...
</script>
이젠 휴지통버튼을 누르면 localstorage에서 내용이 삭제되고 화면에서도 바로 사라진다.
TodoList.vue
에서 App.vue
로 옮길 코드
todoItem.completed = !todoItem.completed;
localStorage.removeItem(todoItem.item);
localStorage.setItem(todoItem.item, JSON.stringify(todoItem));
App.vue
<template>
<div id="app">
...
<!-- <TodoList v-bind:내려보낼 프롭스 속성이름="현재 위치의 컴포넌트 데이터 속성"></TodoList> -->
<TodoList v-bind:propsdata="todoItems" v-on:removeItem="removeOneItem" v-on:toggleItem="toggleOneItem"></TodoList>
<TodoFooter></TodoFooter>
</div>
</template>
<script>
export default {
...,
methods: {
addOneItem: function(todoItem) {
...
},
removeOneItem: function(todoItem, index) {
...
},
toggleOneItem: function(todoItem, index) {
//todoItem.completed = !todoItem.completed;
this.todoItems[index].completed = !this.todoItems[index].completed;
localStorage.removeItem(todoItem.item);
localStorage.setItem(todoItem.item, JSON.stringify(todoItem));
}
},
...
}
</script>
TodoList.vue
<script>
export default {
...,
methods: {
removeTodo: function(todoItem, index) {
...
},
toggleComplete: function(todoItem) {
this.$emit('toggleEvent', todoItem, index);
}
}
}
</script>
TodoFooter.vue
에서 App.vue
로 옮길 코드
localStorage.clear();
App.vue
<script>
export default {
...,
methods: {
addOneItem: function(todoItem) {
...
},
removeOneItem: function(todoItem, index) {
...
},
toggleOneItem: function(todoItem, index) {
...
},
clearAllItems: function() {
localStorage.clear();
this.todoItems = []; //다시 빈 배열로 만들기
}
},
...
}
</script>
TodoFooter.vue
<script>
export default {
methods: {
clearTodo: function() {
this.$emit('clearAll');
}
}
}
</script>