728x90
반응형
개선사항
할 일 추가, 삭제나 Clear All 시 리스트에 바로 반영하기
원인
할 일 추가(TodoInput
), 리스트(TodoList
), Clear All(TodoFooter
) 컴포넌트가 나뉘어져 있어 컴포넌트끼리 변경사항을 전달하지 않았기 때문에 localStorage
에서는 변경사항이 보이지만 화면에서는 확인되지 않는다.
[리팩토링] 할 일 목록 표시 기능
기능
App.vue
로부터props
통신을 사용하여todoItems
를 받아TodoList
에 출력
// App.vue
<template>
<div id="app">
<!-- <TodoList v-bind:내려보낼 프롭스 속성 이름="현재 위치의 컴포넌트 데이터 속성"></TodoList> -->
<TodoList v-bind:propsdata="todoItems"></TodoList>
</div>
</template>
<script>
import TodoList from './components/TodoList.vue'
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: {
'TodoList': TodoList
}
}
</script>
<style>
...
</style>
// TodoList.vue
<template>
<div>
<ul>
<!-- 기존 in todoItems 대신 propsdata 사용 -->
<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)"></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>
</ul>
</div>
</template>
<script>
export default {
props: ['propsdata'],
methods: {
removeTodo: function(todoItem, index) {
localStorage.removeItem(todoItem);
this.todoItems.splice(index, 1);
},
toggleComplete: function(todoItem) {
todoItem.completed = !todoItem.completed;
localStorage.removeItem(todoItem.item);
localStorage.setItem(todoItem.item, JSON.stringify(todoItem));
}
},
}
</script>
<style scoped>
...
</style>
[리팩토링] 할 일 추가 기능
기능
TodoInput
에서event emit
통신을 사용하여 입력 값 전달 및 추가 후 리스트에 바로 반영
// App.vue
<template>
<div id="app">
<!-- <TodoInput v-on:하위 컴포넌트에서 발생시킨 이벤트 이름="현재 컴포넌트의 메소드명"></TodoInput> -->
<TodoInput v-on:addTodoItem="addOneItem"></TodoInput>
<TodoList v-bind:propsdata="todoItems"></TodoList>
</div>
</template>
<script>
import TodoInput from './components/TodoInput.vue'
import TodoList from './components/TodoList.vue'
export default {
data: function() {
return {
todoItems: []
}
},
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))));
}
}
}
},
components: {
'TodoInput': TodoInput,
'TodoList': TodoList
}
}
</script>
<style>
...
</style>
// 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>
</div>
</template>
<script>
export default {
data: function() {
return {
newTodoItem: ''
}
},
methods: {
addTodo: function() {
if(this.newTodoItem !== '') {
// this.$emit('이벤트 이름', 인자1, 인자2, ...);
// event emit으로 추가할 item 전달
this.$emit('addTodoItem', this.newTodoItem);
this.clearInput();
}
},
clearInput: function() {
this.newTodoItem = '';
}
}
}
</script>
<style scoped>
...
</style>
[리팩토링] 할 일 삭제 기능
기능
TodoList
에서event emit
통신을 사용하여 삭제할 값 전달 및 삭제 후 리스트에 바로 반영
// App.vue
<template>
<div id="app">
<TodoList v-bind:propsdata="todoItems" v-on:removeItem="removeOneItem"></TodoList>
</div>
</template>
<script>
import TodoList from './components/TodoList.vue'
export default {
data: function() {
return {
todoItems: []
}
},
methods: {
removeOneItem: function(todoItem, index) {
// localStorage.removeItem(key)
// TodoList에서 todoItem 객체를 받았기 때문에 키 값과 동일한 todoItem.item을 사용해야 한다.
localStorage.removeItem(todoItem.item);
this.todoItems.splice(index, 1);
}
},
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: {
'TodoList': TodoList
}
}
</script>
<style>
...
</style>
// TodoList.vue
<template>
<div>
<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)"></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>
</ul>
</div>
</template>
<script>
export default {
props: ['propsdata'],
methods: {
removeTodo: function(todoItem, index) {
// event emit으로 삭제할 item과 index 전달
this.$emit('removeItem', todoItem, index);
},
toggleComplete: function(todoItem) {
todoItem.completed = !todoItem.completed;
localStorage.removeItem(todoItem.item);
localStorage.setItem(todoItem.item, JSON.stringify(todoItem));
}
},
}
</script>
<style scoped>
...
</style>
[리팩토링] 할 일 완료 기능
기능
TodoList
에서event emit
통신을 사용하여 변경할 값 전달 및 변경 후 리스트에 바로 반영
// App.vue
<template>
<div id="app">
<TodoList v-bind:propsdata="todoItems" v-on:toggleItem="toggleOneItem"></TodoList>
</div>
</template>
<script>
import TodoList from './components/TodoList.vue'
export default {
data: function() {
return {
todoItems: []
}
},
methods: {
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));
}
},
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: {
'TodoList': TodoList
}
}
</script>
<style>
...
</style>
// TodoList.vue
<template>
<div>
<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>
</ul>
</div>
</template>
<script>
export default {
props: ['propsdata'],
methods: {
removeTodo: function(todoItem, index) {
this.$emit('removeItem', todoItem, index);
},
toggleComplete: function(todoItem, index) {
this.$emit('toggleItem', todoItem, index);
}
},
}
</script>
<style scoped>
...
</style>
[리팩토링] 할 일 모두 삭제 기능
기능
TodoFooter
에서 event emit
통신을 사용하여 전체 삭지 및 리스트에 바로 반영
// App.vue
<template>
<div id="app">
<TodoFooter v-on:clearAll="clearAllItems"></TodoFooter>
</div>
</template>
<script>
import TodoFooter from './components/TodoFooter.vue'
export default {
data: function() {
return {
todoItems: []
}
},
methods: {
clearAllItems: function() {
// localStorage 처리 부분
localStorage.clear();
// 화면 스크립트 처리 부분
this.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: {
'TodoFooter': TodoFooter
}
}
</script>
<style>
...
</style>
// TodoFooter.vue
<template>
<div class="clearAllContainer">
<span class="clearAllBtn" v-on:click="clearTodo">Clear All</span>
</div>
</template>
<script>
export default {
methods: {
clearTodo: function() {
this.$emit('clearAll');
}
}
}
</script>
<style scoped>
...
</style>
728x90
반응형
'Dev > Vue.js' 카테고리의 다른 글
[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 |
[Vue.js] Vue CLI (0) | 2020.09.09 |
댓글