开发一个任务列表应用是 Vue 的经典案例,涵盖了数据管理、组件化、状态管理和用户交互等多个方面。以下是设计和实现的具体步骤:
1. 需求分析
一个任务列表应用通常需要以下功能:
- 添加任务:用户可以输入任务内容并添加到列表中。
- 标记任务完成:用户可以标记任务为已完成。
- 删除任务:用户可以删除任务。
- 过滤任务:用户可以查看全部任务、未完成任务或已完成任务。
- 持久化存储:任务列表数据在页面刷新后不丢失。
2. 技术选型
- Vue 3:使用 Composition API 或 Options API。
- Vuex/Pinia:用于状态管理(可选)。
- LocalStorage:用于持久化存储任务列表数据。
- UI 库:如 Element Plus 或 Vant(可选)。
3. 项目结构设计
src/
├── assets/ # 静态资源
├── components/ # 组件
│ ├── TaskList.vue # 任务列表组件
│ ├── TaskItem.vue # 任务项组件
│ └── TaskFilter.vue # 任务过滤组件
├── stores/ # 状态管理
│ └── taskStore.js # 任务状态管理
├── views/ # 页面
│ └── HomeView.vue # 主页
├── App.vue # 根组件
└── main.js # 入口文件
4. 实现步骤
4.1 创建任务状态管理
使用 Vuex 或 Pinia 管理任务列表的状态。
Vuex 示例
// stores/taskStore.js
import { createStore } from 'vuex';
export default createStore({
state: {
tasks: JSON.parse(localStorage.getItem('tasks')) || [],
filter: 'all', // all, active, completed
},
mutations: {
ADD_TASK(state, task) {
state.tasks.push(task);
localStorage.setItem('tasks', JSON.stringify(state.tasks));
},
TOGGLE_TASK(state, id) {
const task = state.tasks.find((task) => task.id === id);
if (task) task.completed = !task.completed;
localStorage.setItem('tasks', JSON.stringify(state.tasks));
},
DELETE_TASK(state, id) {
state.tasks = state.tasks.filter((task) => task.id !== id);
localStorage.setItem('tasks', JSON.stringify(state.tasks));
},
SET_FILTER(state, filter) {
state.filter = filter;
},
},
getters: {
filteredTasks(state) {
if (state.filter === 'active') {
return state.tasks.filter((task) => !task.completed);
} else if (state.filter === 'completed') {
return state.tasks.filter((task) => task.completed);
}
return state.tasks;
},
},
});
Pinia 示例
// stores/taskStore.js
import { defineStore } from 'pinia';
export const useTaskStore = defineStore('task', {
state: () => ({
tasks: JSON.parse(localStorage.getItem('tasks')) || [],
filter: 'all', // all, active, completed
}),
actions: {
addTask(task) {
this.tasks.push(task);
localStorage.setItem('tasks', JSON.stringify(this.tasks));
},
toggleTask(id) {
const task = this.tasks.find((task) => task.id === id);
if (task) task.completed = !task.completed;
localStorage.setItem('tasks', JSON.stringify(this.tasks));
},
deleteTask(id) {
this.tasks = this.tasks.filter((task) => task.id !== id);
localStorage.setItem('tasks', JSON.stringify(this.tasks));
},
setFilter(filter) {
this.filter = filter;
},
},
getters: {
filteredTasks(state) {
if (state.filter === 'active') {
return state.tasks.filter((task) => !task.completed);
} else if (state.filter === 'completed') {
return state.tasks.filter((task) => task.completed);
}
return state.tasks;
},
},
});
4.2 创建任务列表组件
<!-- components/TaskList.vue -->
<template>
<div>
<input v-model="newTask" @keyup.enter="addTask" placeholder="Add a new task" />
<ul>
<TaskItem
v-for="task in filteredTasks"
:key="task.id"
:task="task"
@toggle="toggleTask"
@delete="deleteTask"
/>
</ul>
<TaskFilter @filter="setFilter" />
</div>
</template>
<script>
import { computed, ref } from 'vue';
import { useTaskStore } from '../stores/taskStore';
import TaskItem from './TaskItem.vue';
import TaskFilter from './TaskFilter.vue';
export default {
components: { TaskItem, TaskFilter },
setup() {
const taskStore = useTaskStore();
const newTask = ref('');
const addTask = () => {
if (newTask.value.trim()) {
taskStore.addTask({
id: Date.now(),
text: newTask.value.trim(),
completed: false,
});
newTask.value = '';
}
};
return {
newTask,
filteredTasks: computed(() => taskStore.filteredTasks),
addTask,
toggleTask: taskStore.toggleTask,
deleteTask: taskStore.deleteTask,
setFilter: taskStore.setFilter,
};
},
};
</script>
4.3 创建任务项组件
<!-- components/TaskItem.vue -->
<template>
<li :class="{ completed: task.completed }">
<input type="checkbox" :checked="task.completed" @change="$emit('toggle', task.id)" />
<span>{{ task.text }}</span>
<button @click="$emit('delete', task.id)">Delete</button>
</li>
</template>
<script>
export default {
props: {
task: {
type: Object,
required: true,
},
},
};
</script>
<style scoped>
.completed {
text-decoration: line-through;
}
</style>
4.4 创建任务过滤组件
<!-- components/TaskFilter.vue -->
<template>
<div>
<button @click="$emit('filter', 'all')">All</button>
<button @click="$emit('filter', 'active')">Active</button>
<button @click="$emit('filter', 'completed')">Completed</button>
</div>
</template>
<script>
export default {
emits: ['filter'],
};
</script>
4.5 在主页中使用任务列表
<!-- views/HomeView.vue -->
<template>
<div>
<h1>Task List</h1>
<TaskList />
</div>
</template>
<script>
import TaskList from '../components/TaskList.vue';
export default {
components: { TaskList },
};
</script>
5. 总结
通过以上步骤,可以开发一个功能完整的任务列表应用。关键点包括:
- 状态管理:使用 Vuex 或 Pinia 管理任务列表和过滤状态。
- 组件化:将任务列表、任务项和过滤功能拆分为独立组件。
- 持久化存储:使用 LocalStorage 保存任务列表数据。
- 用户交互:实现添加、标记完成、删除和过滤任务的功能。
这种设计模式清晰、可维护性强,适合扩展和优化。
THE END
暂无评论内容