商店中的状态更新时,Vue组件不会更新

时间:2018-10-08 19:24:21

标签: javascript vue.js

我正在尝试在Vue中创建一个简单的待办事项清单,但我想抽象出所有内容并使用虚拟的REST API,这样我就可以开始习惯于Vue中的生产级项目,这一切都使我很头疼。 GET,PUT和POST请求似乎可以正常工作,但是当我对后端执行成功的POST请求时,我无法弄清楚为什么待办事项列表不会自动更新。

我有一个TodoList组件,该组件遍历todosFiltered()计算的属性以显示待办事项。计算所得的属性返回Vuex存储中的获取器todosFiltered。我还在这里使用created()生命周期钩子在商店中调度一个操作,该操作发出初始GET请求,然后在首次加载页面时在商店中填充一个名为todos的数组。存储区中的吸气剂todosFiltered返回state.todos,因此我假设重新渲染组件时,它将具有从todos抓取的状态中的新todosFiltered数组,只是那没有发生。我在这里想念什么?任何建议将不胜感激。

TodoList.vue

(我知道我必须为id设计一个解决方案,它在我的列表中:p)

<template>
    <div class="container">
        <input v-model="newTodo" type="text" placeholder="What must be done?" class="todo-input" @keyup.enter="addTodo">
        <transition-group name="fade" enter-active-class="animated zoomIn" leave-active-class="animated zoomOut">
            <todo-item v-for="todo in todosFiltered" :key="todo.id" :checkAll="!anyRemaining" :todo="todo"></todo-item>
        </transition-group>
        <div class="extra-container">
            <todos-filtered></todos-filtered>
        </div>
    </div>
</template>

<script>
import TodosFiltered from './TodosFiltered'
import TodoItem from './TodoItem'

export default {
  name: 'todolist',
  components: {
    TodosFiltered,
    TodoItem
  },
  data() {
    return {
        beforeEditCache: '',
        newTodo: '',
        idForTodo: 10,
    }
  },
  // Methods
  methods: {
    addTodo() {
        if (this.newTodo.trim().length == 0) {
            return
        }
        this.$store.dispatch('addTodo', {
            id: this.idForTodo,
            title: this.newTodo,
            completed: false
        })
        this.newTodo = ''
        this.idForTodo++
    }
  },
  computed: {
    todosFiltered() {
        return this.$store.getters.todosFiltered
    },
  },
  created() {
    this.$store.dispatch('loadTodos')
  },
}
</script>

store.js

export const store = new Vuex.Store({
    state: {
        filter: 'all',
        todos: []
    },
    getters: {
        todosFiltered(state) {
            if (state.filter == 'all') {
                return state.todos
            } else if (state.filter == 'active') {
                return state.todos.filter(todo => !todo.completed)
            } else if (state.filter == 'completed') {
                return state.todos.filter(todo => todo.completed)
            }
            return state.todos
        },
        showClearCompleted(state) {
            return state.todos.filter(todo => todo.completed).length > 0
        }
    },
    mutations: {
        addTodo(state, todo) {
            state.todos.push(todo)
        },
        setTodos(state, todos) {
            state.todos = todos
        },
    },
    actions: {
        loadTodos(context) {
            axios.get('http://localhost:3000/todos')
            .then(r => r.data)
            .then(todos => {
                context.commit('setTodos', todos)
            })
        },
        updateTodo(context, todo) {
            axios.put('http://localhost:3000/todos/' + todo.id, {
                "id": todo.id,
                "title": todo.title,
                "completed": todo.completed
            })
        },
        addTodo(context, todo) {
            axios.post('http://localhost:3000/todos', {
                "id": todo.id,
                "title": todo.title,
                "completed": todo.completed
            })
            .then(todo => {
                context.commit('addTodo', todo)
            })
        },
    }
})

编辑:这是当我添加待办事项时Vue Dev Tools中的操作-商店状态的todos立即更新,并且todosFiltered组件中的TodoList计算属性还反映了这一点-但新的待办事项没有出现在列表中!奇怪。

2 个答案:

答案 0 :(得分:0)

问题是在v-for循环上使用了$ store.getter。 请尝试以下操作:

  1. 将您的计算结果设置为

    todos(){      返回this。$ store.todos; }

  2. 更改您的v-for循环以在待办事项中使用待办事项

  3. 将v-if条件添加到循环中,例如v-if =“ filtered(todo)”
  4. 创建一个称为filtered(或您喜欢的任何一种)的新方法,并在其中添加“ filteredTodos”逻辑,并根据需要返回true / false。
  5. 如果您需要共享此代码,则始终可以使用mixin并在各个组件之间共享它。

希望这对您有用

答案 1 :(得分:0)

解决此问题的一种方法可以是创建我喜欢的refresh()方法。

基本上,您的todos方法中将有data()的本地列表,refresh()方法会将商店中的所有todos加载到本地{{ 1}}列表,每次您执行某项操作(例如创建,删除或更新)时,都将调用refresh方法为您重新加载列表。

因此,在您的todos中:

TodoList.vue
  

实际上不删除您已有的东西,而是将其替换为   这样,只需将此处的内容应用于您的代码即可。

相关问题