【问题标题】:Vuex getter for filter not updating after mutating array of stateVuex getter 过滤器在改变状态数组后不更新
【发布时间】:2020-05-07 23:54:50
【问题描述】:

我正在构建一个待办事项应用程序。有一个按钮可以切换所有待办事项的检查/完成状态。我正在改变state 的数组,但getters 没有更新。当我单击toggle complete 按钮时,数据库和数组state.todos 会更新,但$store.getters.filteredTodos 不会更新。

所以有些待办事项显示不正确(一些被选中,而另一些则没有,应该全部选中或取消选中)

    // in getters
    filteredTodos(state) {
        if (state.filter == 'active') {
            return state.todos.filter(todo => !todo.completed);
        }

        if (state.filter == 'completed') {
            return state.todos.filter(todo => todo.completed);
        }

        return state.todos;
    },

    // in mutations
    retrieveTodos(state, todos) {
        Vue.set(state, 'todos', todos);

        // tried the following, but also didn't work
        //state.todos.splice(0, state.todos.length, ...todos);
    },

    // in actions
    toggleCompleted(context, completed) {
        axios.patch('/todos/toggle-completed', {completed})
            // response.data is the array of the updated todo items
            .then(response => context.commit('retrieveTodos', response.data))
            .catch(e => console.log(e));
    },

从 StackOverflow 和 VueForum 的几篇文章中,我看到了相同的解决方案:

        Vue.set(state, 'todos', todos);
        // or
        state.todos.splice(0, state.todos.length, ...todos);

他们都没有工作。 $store.state 会更新,但 $store.getters.filteredTodos 不会。

如何解决?

更新

我正在关注 this tutorial series on YouTube 以开始使用 Vue,但我正在自己做一些事情。在教程中,这个家伙为前端创建了一个 Vue 项目,为后端创建了一个 Laravel 项目。我也是这样做的。

【问题讨论】:

  • 在你的突变中,不简单地做state.todos = todos 工作吗?此外,当您显示待办事项时,我假设您正在循环使用v-for。您使用的是什么:key 值?
  • 我这样做了。我最初写了state.todos = todos,但它也没有更新getter 函数。它仅适用于更新state,但我也需要更新filteredTodos:key 等于待办事项的 id。
  • 你能复制这个并通过codesandbox.io分享链接吗?
  • 是的。我编辑了问题。请看一下。你可以 git clone my repos 来模拟问题
  • 我发现错误是什么 getter 正在正确更新,但没有更新的是 TodoItem 组件。我找到了解决方案,稍后会在这里发布

标签: arrays vue.js state vuex getter


【解决方案1】:

我发现问题与gettersstate 无关。两者都以我尝试的三种方式正确更新。

问题出在Todo 组件中。以前,代码是这样的:

// in the template 
        <label class="todo-action" :for="`todo-checked-${id}`">
            <input type="checkbox" v-model="completed" 
                   :id="`todo-checked-${id}`" @change="update">
        </label>

        <div class="todo-title">
            {{title}}
        </div>

// inside script tag
    data() {
        // this allow me to access this.id, this.completed, and this.title 
        // instead of this.todo.id, this.todo.completed, and this.todo.title
        return this.todo;
    },

问题是data 没有更新。我将其修复如下

// in the template I access the props from the todo item, so it is always up to date
        <label class="todo-action" :for="`todo-checked-${todo.id}`">
            <input type="checkbox" v-model="todo.completed" 
                   :id="`todo-checked-${todo.id}`" @change="update">
        </label>

        <div class="todo-title">
            {{todo.title}}
        </div>

是的,这是一个非常简单的解决方案

【讨论】:

    猜你喜欢
    • 2019-08-06
    • 1970-01-01
    • 2019-11-30
    • 2021-03-22
    • 2018-05-28
    • 1970-01-01
    • 2019-06-08
    • 2021-10-26
    • 2020-08-04
    相关资源
    最近更新 更多