Vue迁移Vuex后任务按优先级/最新时间排序功能失效求助
问题:迁移Vuex后任务排序功能失效
将原有Vue项目引入Vuex后,任务按优先级或创建时间排序的功能完全失效。添加新任务能正常显示对应数据,但无论怎么编写sortedTasks函数都无法实现排序效果,且控制台无任何报错信息。
组件代码(Vue)
import '@/assets/main.css' import { computed } from 'vue' import { useStore } from 'vuex' export default { computed: { inputTitle: { get() { return this.$store.state.inputTitle }, set(value) { this.$store.commit('SET_INPUT_TITLE', value) } }, inputContent: { get() { return this.$store.state.inputContent }, set(value) { this.$store.commit('SET_INPUT_CONTENT', value) } }, inputCategory: { get() { return this.$store.state.inputCategory }, set(value) { this.$store.commit('SET_INPUT_CATEGORY', value) } }, sortingOptions: { get() { return this.$store.state.sortingOptions }, set(value) { this.$store.commit('SET_SORTING_OPTION', value) } } }, methods: { addTask() { this.$store.dispatch('addTask') }, removeTask(task) { this.$store.commit('REMOVE_TASK', task) }, updateSortingOption() { this.$store.commit('SET_SORTING_OPTION', this.sortingOptions) } } } </script> <template> <main class="app"> <section class="greeting"> <h2 class="title">Welcome Back</h2> </section> <!-- Task Section --> <section class="create-task"> <h3>CREATE A TASK</h3> <form id="new-task-form" @submit.prevent="addTask"> <h4>What's on your task list?</h4> <input type="text" name="title" id="title" placeholder="Title of task" v-model="inputTitle" /> <input type="text" name="content" id="content" placeholder="e.g. code todo app" v-model="inputContent" /> <!-- Priority Selector --> <h4>Priority</h4> <div class="options"> <label> <input type="radio" name="category" value="high" v-model="inputCategory" /> <span class="bubble high"></span> <div>High</div> </label> <label> <input type="radio" name="category" value="medium" v-model="inputCategory" /> <span class="bubble medium"></span> <div>Medium</div> </label> <label> <input type="radio" name="category" value="low" v-model="inputCategory" /> <span class="bubble low"></span> <div>Low</div> </label> </div> <!-- Dropdown to select sorting option --> <input type="submit" value="Add task" /> </form> <div> <label class="sort" for="sort-select">Sort by:</label> <select id="sort-select" v-model="sortingOptions"> <option value="created_at">Most Recent</option> <option value="priority">Priority</option> </select> </div> </section> <!-- New Task Handler --> <section class="task-list"> <h3>TASK LIST</h3> <div class="list" id="task-list"> <div :key="i" v-for="(task, i) in $store.getters.sortedTasks" :class="`task-item ${task.done && 'done'}`" > {{ $store.state.tasks }} <label> <input type="checkbox" v-model="task.done" /> <span :class="`bubble ${task.category === 'high' ? 'high' : task.category === 'medium' ? 'medium' : 'low'}`" ></span> </label> <div class="task-content"> <div> <div class="inputContent" value="inputContent"></div> </div> <input type="text" v-model="task.title" /> <input type="text" v-model="task.content" /> </div> <div class="actions"> <button class="delete" @click="removeTask(task)">Delete</button> </div> </div> </div> </section> </main> <RouterView /> </template>
Vuex Store代码
export default createStore({ state: { tasks: [], inputTitle: '', inputContent: '', inputCategory: null, sortingOptions: 'created_at' }, mutations: { ADD_TASK(state, task) { state.tasks.push(task) // console.log(task) }, REMOVE_TASK(state, task) { state.tasks = state.tasks.filter((t) => t !== task) }, SET_INPUT_TITLE(state, title) { state.inputTitle = title }, SET_INPUT_CONTENT(state, content) { state.inputContent = content }, SET_INPUT_CATEGORY(state, category) { state.inputCategory = category }, SET_SORTING_OPTION(state, category) { state.sortingOptions = category } }, actions: { addTask({ commit, state }) { if (state.inputContent.trim() === '' || state.inputCategory === null) { return } const newTask = { title: state.inputTitle, content: state.inputContent, category: state.inputCategory, done: false, editable: false, createdAt: new Date().getTime() } commit('ADD_TASK', newTask) commit('SET_INPUT_TITLE', '') commit('SET_INPUT_CONTENT', '') commit('SET_INPUT_CATEGORY', null) commit('SET_SORTING_OPTION', null) } }, getters: { sortedTasks(state) { if (state.sortingOptions === 'created_at') { // Sort by createdAt timestamp return state.tasks.slice().sort((a, b) => a.createdAt - b.createdAt) } else if (state.sortingOptions === 'priority') { // Sort by priority (high > medium > low) const priorityOrder = { high: 1, medium: 2, low: 3 } return state.tasks.slice().sort((a, b) => { return priorityOrder[a.category] - priorityOrder[b.category] }) } return state.tasks.slice() } } })
问题根源及修复方案
1. 添加任务后排序选项被重置为null
在addTask Action的最后,错误执行了commit('SET_SORTING_OPTION', null),导致sortingOptions被设为null,sortedTasks getter中的两个排序条件都不匹配,直接返回未排序的任务数组。
修复:删除该行代码,保留当前排序选项。
2. 创建时间排序方向错误
当前created_at排序逻辑是a.createdAt - b.createdAt,会让最早创建的任务排在前面,与“Most Recent(最新)”的预期相反。
修复:改为b.createdAt - a.createdAt,实现最新任务在前的排序效果。
3. 冗余调试代码干扰页面
模板中{{ $store.state.tasks }}会直接渲染整个任务数组,属于调试残留,需删除避免影响展示。
4. 无用方法可移除
组件中的updateSortingOption方法无实际作用,因为select已经通过v-model="sortingOptions"自动触发mutation更新状态,可直接删除。
修复后的关键代码片段
修复后的Vuex Action
actions: { addTask({ commit, state }) { if (state.inputContent.trim() === '' || state.inputCategory === null) { return } const newTask = { title: state.inputTitle, content: state.inputContent, category: state.inputCategory, done: false, editable: false, createdAt: new Date().getTime() } commit('ADD_TASK', newTask) commit('SET_INPUT_TITLE', '') commit('SET_INPUT_CONTENT', '') commit('SET_INPUT_CATEGORY', null) // 移除错误的排序选项重置 // commit('SET_SORTING_OPTION', null) } }
修复后的Getter
getters: { sortedTasks(state) { if (state.sortingOptions === 'created_at') { // 修改为降序,最新任务在前 return state.tasks.slice().sort((a, b) => b.createdAt - a.createdAt) } else if (state.sortingOptions === 'priority') { const priorityOrder = { high: 1, medium: 2, low: 3 } return state.tasks.slice().sort((a, b) => { return priorityOrder[a.category] - priorityOrder[b.category] }) } return state.tasks.slice() } }
修复后的模板片段
<div :key="i" v-for="(task, i) in $store.getters.sortedTasks" :class="`task-item ${task.done && 'done'}`" > <!-- 移除调试用的数组渲染代码 --> <label> <input type="checkbox" v-model="task.done" /> <span :class="`bubble ${task.category === 'high' ? 'high' : task.category === 'medium' ? 'medium' : 'low'}`" ></span> </label> <!-- 其余内容不变 --> </div>
内容的提问来源于stack exchange,提问作者Colton Skiera
相关产品推荐
相关产品推荐

