[to-do-app] TodoList 컴포넌트 구현
🧶 𝗪𝗲𝗯/Vue

[to-do-app] TodoList 컴포넌트 구현

 

 TodoList 컴포넌트 구현 

Life Cycle

https://v3.ko.vuejs.org/api/options-lifecycle-hooks.html

 

라이프사이클 훅 | Vue.js

라이프사이클 훅 Note 모든 라이프사이클 훅은 자동으로 this 컨텍스트가 인스턴스에 바인딩되어 있으므로, data, computed 및 methods 속성에 접근할 수 있습니다. 즉, 화살표 함수를 사용해서 라이프사

v3.ko.vuejs.org

// vue life cycle
created() {
    console.log("created");

    // 로컬스토리지에 데이터가 있다면
    if (localStorage.length > 0) {
        for (let i = 0; i < localStorage.length; i++) {
            if (localStorage.key(i) !== "loglevel:webpack-dev-server") {
                // JSON.parse : str -> json 변경
                let item = JSON.parse(
                    localStorage.getItem(localStorage.key(i))
                );

                this.todoItems.push(item);
            }
        }
    }
},

created 는 인스턴스가 생성된 후의 단계입니다.

이때 로컬스토리지에 저장된 데이터들을 todoItems[] 배열로 읽어들여 데이터를 사용합니다.

created 때 해당 함수를 사용하는 이유는, 데이터를 사용하려할 때 만약 해당 데이터가 todoItems에 담겨있지 않다면 사용할 수 없기 때문입니다.

 

localStorage.getItem(key) 함수를 이용하여 로컬스토리지에 저장된 데이터를 가져올 수 있습니다.

Arrays.push() 함수를 사용하면 요소를 배열에 저장할 수 있습니다.

 

 

 

v-for

https://kr.vuejs.org/v2/guide/list.html

 

리스트 렌더링 — Vue.js

Vue.js - 프로그레시브 자바스크립트 프레임워크

kr.vuejs.org

v-for
: 디렉티브를 사용하여 배열을 기반으로 리스트를 렌더링 할 수 있다.

todoItems 배열에 담겨있는 데이터가 리스트로 렌더링 됩니다.

v-for 디렉티브는 item in items 형태의 특별한 문법이 필요합니다. 여기서 items는 배열이고 item은 반복되는 배열의 요소 별칭 입니다.

 

<ul>
    <li
        v-for="(item, index) in todoItems"
        v-bind:key="index"
        class="shadow"
    ><
    {{item}}
    </li>
</ul>

 만약 (item, index) in todoItems 를 했다면 (배열의 요소, 배열의 인덱스) 둘 모두를 꺼내올 수 있습니다.

in 키워드 대신에 of 를 사용할 수도 있습니다. 

for item in object 로 (키, 쌍)을 가진 객체를 가져오는 경우라면 (key, value, index) 요소 세가지 모두를 가져올 수 있습니다.

 

 

리스트 요소 삭제하기

// 리스트 요소 삭제
removeTodo(todoItem, index) {
    localStorage.removeItem(todoItem.item);
    this.todoItems.splice(index, 1);
},

localStorage.removeItem(key) 를 하면 해당 키의 값을 로컬스토리지에서 삭제할 수 있습니다.

splice(지울 요소의 시작 인덱스, 지울 갯수) 함수를 이용하면 배열에서 요소를 삭제할 수 있습니다.

 

 

리스트 요소 체크하기

<i
    class="fa-solid fa-check checkBtn"
    v-on:click="toggleComplete(item)"
></i>
<span v-bind:class="{ textCompleted: item.completed }">
    {{ item.item }}
</span>
// 리스트 요소 체크
toggleComplete(todoItem) {
    todoItem.completed = !todoItem.completed;
    localStorage.removeItem(todoItem.item);
    localStorage.setItem(todoItem.item, JSON.stringify(todoItem)); // 갱신
},

JSON으로 로컬 스토리지에 객체 형태로 넣습니다. 이때 JSON.stringfy() 함수를 사용해야 문자열 형태로 넣을 수 있습니다.

item의 completed 를 변경합니다. 만약 true 면 false로 false면 true로 변경할 수 있씁니다.

localStorage 는 업데이트 함수가 없기 때문에 삭제를 하고 다시 setItem() 으로 데이터를 저장해야합니다.

 

 

v-bind

https://kr.vuejs.org/v2/guide/class-and-style.html

v-bind
: 데이터 바인딩은 element의 클래스 목록과 인라인 스타일을 조작하기 위해 일반적으로 사용된다. 이 두 속성은 v-bind를 사용하여 처리할 수 있다.

v-bind 를 통해서 class를 바인딩 할 수 있습니다. 해당 클래스를 끄고 켜고를 해당 바인딩을 통해 이용할 수 있습니다.

style와도 사용이 가능합니다.

 

 

components/TodoList.vue

<template>
	<div>
		<ul>
			<li
				v-for="(item, index) in todoItems"
				v-bind:key="index"
				class="shadow"
			>
				<i
					class="fa-solid fa-check checkBtn"
					v-on:click="toggleComplete(item)"
				></i>
				<span v-bind:class="{ textCompleted: item.completed }">
					{{ item.item }}
				</span>

				<span class="removeBtn" v-on:click="removeTodo(item, index)">
					<i class="fa-solid fa-trash"></i>
				</span>
			</li>
		</ul>
	</div>
</template>

<script>
/* eslint-disable no-unused-vars */
export default {
	data() {
		return {
			todoItems: [], // 로컬스토리지 저장된 메모 리스트
		};
	},

	methods: {
		// 리스트 요소 체크
		toggleComplete(todoItem) {
			todoItem.completed = !todoItem.completed;
			localStorage.removeItem(todoItem.item);
			localStorage.setItem(todoItem.item, JSON.stringify(todoItem)); // 갱신
		},

		// 리스트 요소 삭제
		removeTodo(todoItem, index) {
			localStorage.removeItem(todoItem.item);
			this.todoItems.splice(index, 1);
		},
	},

	// vue life cycle
	created() {
		console.log("created");

		// 로컬스토리지에 데이터가 있다면
		if (localStorage.length > 0) {
			for (let i = 0; i < localStorage.length; i++) {
				if (localStorage.key(i) !== "loglevel:webpack-dev-server") {
					// JSON.parse : str -> json 변경
					let item = JSON.parse(
						localStorage.getItem(localStorage.key(i))
					);

					this.todoItems.push(item);
				}
			}
		}
	},
};
</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;
}
.checkBtnCompleted {
	color: #b3adad;
}
.textCompleted {
	text-decoration: line-through;
	color: #b3adad;
}
.removeBtn {
	margin-left: auto;
	color: #de4343;
}
/* 리스트 트랜지션 */
.list-item {
	display: inline-block;
	margin-right: 10px;
}
.list-enter-active,
.list-leave-active {
	transition: all 0.4s;
}
.list-enter, .list-leave-to /* .list-leave-active below version 2.1.8 */ {
	opacity: 0;
	transform: translateY(30px);
}
</style>

 

 

 

 

 

 

뷰 투두앱

vue todo

vue v-bind

vue v-for

vue localstorage


 

728x90