일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
- pwa적용하기
- vitepwa
- sqld
- 싸피
- js
- 셀프넘버
- git
- db
- SSAFY
- react
- 14658
- 플로이드워셜
- 머신러닝종류
- queryset
- 싸피10기
- 알고리즘
- VITE
- PWA
- 데코레이터
- 백준
- unionfind
- Python
- 싸피셜
- TypeScript
- SSAFYcial
- Django
- QuerySetAPI
- 리액트
- SQL
- Javascript
- Today
- Total
Meme's IT
[Vue] Pinia 써보기 - Todo List 만들기 본문
0. 틀만들기
TodoListItem.vue, TodoList.vue, TodoForm.vue 컴포넌트 만들고
TodoList.vue만 다음과 같이 작성, 나머지는 기본틀에 template에 파일 제목만
// TodoList.vue
<template>
<div>
<TodoListItem />
</div>
</template>
<script setup>
import TodoListItem from '@/components/TodoListItem.vue';
</script>
<style scoped>
</style>
// App.vue
<template>
<div>
<h1>Todo PJT</h1>
<TodoForm/>
<TodoList/>
</div>
</template>
<script setup>
import TodoForm from './components/TodoForm.vue';
import TodoList from './components/TodoList.vue';
</script>
<style scoped>
</style>
counters.js도 수정해준다
// counters.js
import { ref, computed } from 'vue'
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', () => {
let id = 0
const todos = ref([
{id: id ++, text: 'todo 1', isDone: false},
{id: id ++, text: 'todo 2', isDone: false},
])
return { todos }
})
1. 조회
이 todos를 누가 가져가는게 맞는지 생각해보자
app에는 todoform에서 사용하지 않으므로 굳이 필요없음.
TodoList에서 가져가자
<template>
<div>
{{ store.todos }}
<TodoListItem
v-for="todo in store.todos"
:key="todo.id"
:todo-data="todo"
/>
</div>
</template>
<script setup>
import TodoListItem from '@/components/TodoListItem.vue'
import { useCounterStore } from '@/stores/counter'
const store = useCounterStore()
</script>
그리고, TodoListItem에서 받아서 써보자
<template>
<div>
{{ todoData.text }}
</div>
</template>
<script setup>
defineProps({
todoData : Object
})
</script>
2. Todo 생성하기
state(todo)에 데이터를 생성하는 것 → action으로 하자
그래서 counter.js에 addTodo라는 action을 추가해줌
const addTodo = function () {
todos.value.push({
id: id++,
// 여기에 사용자 입력 데이터 → TodoForm
text: todoText,
isDone: false
})
}
그리고 TodoForm.vue에서 입력을 받을 form을 만들어줌
<template>
<div>
<p>todoForm</p>
<form @submit.prevent="createTodo()" ref="formElement">
<input type="text" v-model="todoText">
<input type="submit">
</form>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
import { ref } from 'vue'
const todoText = ref('')
const store = useCounterStore()
const formElement = ref(null) // form 입력 후 초기화용 (다른 값 들어가도 상관없음)
const createTodo = function () {
store.addTodo(todoText.value)
formElement.value.reset()
}
</script>
3. 삭제하기
todos 조회해서 어떤걸 삭제했는지 찾고, 지우고 지운것을 다시 todos에 할당
todoListItem에서 우선 delete버튼 하나씩 만들어주고
<template>
<div>
{{ todoData.text }}
<button @click="store.deleteTodo(todoData.id)">delete</button>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
const store = useCounterStore()
defineProps({
todoData : Object
})
</script>
그리고 counter.js에서 지우는 action 만들어주기
const deleteTodo = function (todoId) {
// todos에서 몇번째가 삭제되었는지 검색
const idx = todos.value.findIndex((todo) => todo.id === todoId)
// 배열에서 요소 제거 후 업데이트
todos.value.splice(idx, 1)
}
4. 업데이트
todo의 완료 유무를 표현해보자
항목을 클릭하면 완료를 표시하기 위해 span을 줘서 click에 대한 v-on과
스타일을 주기위한 class v-bind를 적용
// todoListItem.vue
<template>
<div>
<!-- 클릭했을 때 updateTodo함수를 통해 isDone을 바꿔주고,
v-bind를 통해 클래스로 완료 스타일을 적용 -->
<span
@click="store.updateTodo(todoData.id)"
:class="{ 'is-done' : todoData.isDone }">
{{ todoData.text }}
</span>
<button @click="store.deleteTodo(todoData.id)">delete</button>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
const store = useCounterStore()
defineProps({
todoData : Object
})
</script>
<style scoped>
.is-done {
text-decoration: line-through;
}
</style>
그리고 counter.js에 todoUpdate action을 만들어준다.
const updateTodo = function(todoId) {
todos.value = todos.value.map((todo) =>{
if ( todo.id === todoId) {
todo.isDone = !todo.isDone
}
return todo
})
# computed를 통해 완료된 todo 개수 계산
counter.js에서 완료된 todo의 갯수를 계산해주는 함수를 작성
const updateTodo = function(todoId) {
todos.value = todos.value.map((todo) =>{
if ( todo.id === todoId) {
todo.isDone = !todo.isDone
}
return todo
})
}
그리고 App.vue에서 출력
<h2>완료된 Todo: {{ store.doneTodosCount }}</h2>
# Plugin - persistedstate
Pinia의 플러그인(plugin) 중에 하나
웹 애플리케이션의 상태(state)를 브라우저의 local storage나 session storage에
영구적으로 저장하고 복원하는 기능
명령어를 통해 설치
npm i pinia-plugin-persistedstate
// vue파일에서 import하기
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
app.use(pinia)
// counter.js에서 return 뒤에 ,이후에 추가
return { ... }
}, { persist: true })
이렇게 추가해주면 이제 새로고침해도 안 없어짐!!!
'FrontEnd > Vue' 카테고리의 다른 글
[Vue] Pinia의 구성 요소 (0) | 2023.11.13 |
---|---|
[Vue] State Management (0) | 2023.11.13 |
[Vue] Axios (1) | 2023.11.10 |
[Vue] Router(3) Navigation Guard (0) | 2023.11.09 |
[Vue] Router(2) 프로그래밍 방식 네비게이션 (0) | 2023.11.09 |