You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

选择待办事项列表时TodoList组件未更新问题求助

TodoList组件未随状态更新的排查与解决

我有两个组件:TodoList和TodoListsList,分别从todos.js和todoLists.js模块的状态中获取数据。当选择某条待办事项列表并标记为活跃状态时,TodoListsList组件会正常更新,但TodoList组件却没有更新,尽管控制台显示todosState.todos的数据已经完成更新。

相关代码实现

todoLists.js中的todoListsState与markAsActive()

import todos from '@/modules/todos.js'

// ... some code ...

const todoListsState = reactive({
    todoLists: [],
    todoListsAreLoading: false,
    removedTodoListId: null,
    editedTodoListId: null,
    editedTodoListName: '',
    baseTodoListsApiUrl: process.env.VUE_APP_BASE_TODO_LISTS_API_URL,
    todoListCreationFormModalId: 'todoListCreationFormModal',
    todoListNameChangeFormModalId: 'todoListNameChangeFormModal'
});

// ... some code ...

function markAsActive(value) {
    let { close } = infoToast();
    if (value) {
        axios.post((todoListsState.baseTodoListsApiUrl + 'mark-as-active'), {
            activatedTodoListId: value
        }).then(function () {
            getTodoLists();
            const { getTodos } = todos();
            getTodos();
        }).catch(function () {
            dangerToast('Failed to mark to-do list as active.');
        }).finally(() => {
            close();
        });
    }
}

todos.js中的todosState与getTodos()

const todosState = reactive({
    todos: [],
    activeTodoListId: 0,
    removedTodoId: null,
    editedTodoId: null,
    editedTodoText: '',
    todosAreLoading: false,
    baseTodosApiUrl: process.env.VUE_APP_BASE_TODOS_API_URL,
    todoAdditionFormModalId: 'todoAdditionFormModal',
    todoEditFormModalId: 'todoEditFormModal'
});

// ... some code ...

async function getTodos() {
    try {
        todosState.todosAreLoading = true;
        const response = await axios.get(todosState.baseTodosApiUrl);
        todosState.activeTodoListId = response.data[0];
        todosState.todos = response.data[1];
    } catch (e) {
        dangerToast('To-dos loading failed.');
    } finally {
        todosState.todosAreLoading = false;
    }
}

排查发现

控制台打印的todosState.todos数据已成功更新,且确认数组未丢失响应式特性,但TodoList组件始终未触发重新渲染。

问题原因

核心问题在于todos.js的导出方式:如果todos.js是通过工厂函数(调用函数返回状态和方法)的形式导出,那么每次调用todos()都会创建一个全新的reactive状态实例。

  • TodoList组件引用的是某一次调用todos()生成的状态实例
  • markAsActive中调用todos()得到的是另一个全新实例,调用getTodos()更新的是这个新实例的状态,和组件引用的不是同一个对象,自然无法触发组件更新。

解决方法

将todos.js改为单例模式,确保全局只存在一个状态实例:

修改todos.js的导出方式

import { reactive } from 'vue';
import axios from 'axios';
// 导入你的toast方法...

const todosState = reactive({
    todos: [],
    activeTodoListId: 0,
    removedTodoId: null,
    editedTodoId: null,
    editedTodoText: '',
    todosAreLoading: false,
    baseTodosApiUrl: process.env.VUE_APP_BASE_TODOS_API_URL,
    todoAdditionFormModalId: 'todoAdditionFormModal',
    todoEditFormModalId: 'todoEditFormModal'
});

async function getTodos() {
    try {
        todosState.todosAreLoading = true;
        const response = await axios.get(todosState.baseTodosApiUrl);
        todosState.activeTodoListId = response.data[0];
        todosState.todos = response.data[1];
    } catch (e) {
        dangerToast('To-dos loading failed.');
    } finally {
        todosState.todosAreLoading = false;
    }
}

// 直接导出单例的状态和方法,而非工厂函数
export default {
    todosState,
    getTodos
};

修改todoLists.js中的调用方式

// 导入单例,不再调用函数
import todos from '@/modules/todos.js'

// ... some code ...

function markAsActive(value) {
    let { close } = infoToast();
    if (value) {
        axios.post((todoListsState.baseTodoListsApiUrl + 'mark-as-active'), {
            activatedTodoListId: value
        }).then(function () {
            getTodoLists();
            // 直接调用单例上的getTodos
            todos.getTodos();
        }).catch(function () {
            dangerToast('Failed to mark to-do list as active.');
        }).finally(() => {
            close();
        });
    }
}

这样一来,TodoList组件和markAsActive函数操作的是同一个todosState实例,当getTodos更新状态后,组件会正常响应并重新渲染。

内容的提问来源于stack exchange,提问作者user18630923

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 13:24:28