Vuex Todo App Example
by flourscent
HTML
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>
<div id="app"></div>
<!-- App.vue 파일의 템플릿 부분 -->
<template id="app-template">
<div>
<h2>태스크 목록</h2>
<ul>
<li v-for="task in tasks" v-bind:key="task.id">
<input type="checkbox" v-bind:checked="task.done" v-on:change="toggleTaskStatus(task)">
{{ task.name }}
-
<span v-for="id in task.labelIds" v-bind:key="id">
{{ getLabelText(id) }}
</span>
</li>
</ul>
<form v-on:submit.prevent="addTask">
<input type="text" v-model="newTaskName" placeholder="새 태스크">
</form>
<h2>레이블 목록</h2>
<ul>
<li v-for="label in labels" v-bind:key="label.id">
<input type="checkbox" v-bind:value="label.id" v-model="newTaskLabelIds">
{{ label.text }}
</li>
</ul>
<form v-on:submit.prevent="addLabel">
<input type="text" v-model="newLabelText" placeholder="새 레이블">
</form>
<h2>레이블로 필터링</h2>
<ul>
<li v-for="label in labels" v-bind:key="label.id">
<input type="radio" v-bind:checked="label.id === filter" v-on:change="changeFilter(label.id)">
{{ label.text }}
</li>
<li>
<input type="radio" v-bind:checked="filter == null" v-on:change="changeFilter(null)">
필터링 없음
</li>
</ul>
<h2>저장 및 복원</h2>
<button type="button" v-on:click="save">저장</button>
<button type="button" v-on:click="restore">복원</button>
</div>
</template>
JavaScript
// store.js
const store = new Vuex.Store({
state: {
// 태스크 초기 스테이트
tasks: [
{
id: 1,
name: '우유 사기',
labelIds: [1, 2],
done: false
},
{
id: 2,
name: 'Vue.js 관련 책 사기',
labelIds: [1, 3],
done: true
}
],
// 레이블 초기 스테이트
labels: [
{
id: 1,
text: '쇼핑'
},
{
id: 2,
text: '음료'
},
{
id: 3,
text: '책'
}
],
// 다음에 추가할 태스크, 레이블 ID
// 실제 애플리케이션이라면 서버에서 생성하거나 UUID 등을 사용함
nextTaskId: 3,
nextLabelId: 4,
// 필터링 적용 레이블 ID
filter: null
},
getters: {
// 필터링된 태스크 목록을 반환
filteredTasks (state) {
// 레이블이 선택되지 않았다면 태스크 목록을 그대로 반환
if (!state.filter) {
return state.tasks
}
// 선택된 레이블로 필터링 적용
return state.tasks.filter(task => {
return task.labelIds.indexOf(state.filter) >= 0
})
}
},
mutations: {
// 태스크 추가하기
addTask (state, { name, labelIds }) {
state.tasks.push({
id: state.nextTaskId,
name,
labelIds,
done: false
})
// 다음에 추가할 테스크의 ID 업데이트
state.nextTaskId++
},
// 태스크 완료 상태 토글
toggleTaskStatus (state, { id }) {
const filtered = state.tasks.filter(task => {
return task.id === id
})
filtered.forEach(task => {
task.done = !task.done
})
},
// 레이블 추가하기
addLabel (state, { text }) {
state.labels.push({
id: state.nextLabelId,
text
})
// 다음에 추가할 레이블 ID 업데이트
state.nextLabelId++
},
// 필터링 대상 레이블 변경
changeFilter (state, { filter }) {
state.filter = filter
},
// 스테이트 복원
restore (state, { tasks, labels, nextTaskId, nextLabelId }) {
state.tasks = tasks
state.labels = labels
state.nextTaskId = nextTaskId
state.nextLabelId = nextLabelId
}
},
actions: {
// 로컬 스토리지에 스테이트를 저장
...