[英]Vue component doesn't update when state in store is updated
我试图在Vue中创建一个简单的待办事项清单,但我想抽象出所有内容并使用虚拟的REST API,这样我就可以开始习惯于Vue中的生产级项目,这一切都使我很头疼。 GET,PUT和POST请求似乎可以正常工作,但是当我对后端执行成功的POST请求时,我无法弄清楚为什么待办事项列表不会自动更新。
我有一个TodoList
组件,该组件遍历todosFiltered()
计算属性以显示todosFiltered()
。 计算出的属性返回到Vuex存储中的getter todosFiltered
。 我还使用此处的created()
生命周期钩子在商店中调度一个操作,该操作发出初始GET请求,然后在首次加载页面时在商店中填充一个称为todos
的数组。 存储todosFiltered
中的getter todosFiltered
返回state.todos
,因此我假设当我的组件重新渲染时,它将具有从todosFiltered
抓取的状态中的新todos
数组,只有这种情况没有发生。 我在这里想念什么? 任何建议将不胜感激。
(我知道我必须为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>
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的开发工具,当我加入待办事项- todos
在店内的状态将立即被更新,并且todosFiltered
在计算财产TodoList
分量也反映了-但新的待办事项不会出现在列出! 奇怪。
问题是在v-for循环上使用了$ store.getter。 请尝试以下操作:
设置您的计算为
todos(){返回this。$ store.todos; }
更改v-for循环以在待办事项中使用待办事项
希望这对你有用
解决此问题的一种方法可以是创建我喜欢调用的refresh()
方法。
基本上,你将有一个本地列表todos
在data()
方法中, refresh()
方法将所有负载todos
从商店到本地todos
列表,每次你做一个动作时,如创建,删除或更新后,您将调用refresh方法为您重新加载列表。
因此,在您的TodoList.vue
:
<template>
<todo-item v-for="todo in todosFiltered" :key="todo.id"></todo-item>
</template>
<script>
export default {
data() {
return {
// Where we store the local list of Todos
// so the component will react when we do something to it
todosFiltered: []
}
},
methods {
refresh() {
// Get the todo list from the store.
// which in turn will trigger a change event so the component
// react to what we did.
this.todosFiltered = this.$store.getters.todosFiltered;
},
addTodo() {
this.$store.dispatch('addTodo').then(() => {
// Refresh the list after adding a new Todo
this.refresh();
})
},
updateTodo() {
this.$store.dispatch('updateTodo').then(() => {
// Refresh the list after updating a Todo
this.refresh();
})
},
deleteTodo() {
this.$store.dispatch('deleteTodo').then(() => {
// Refresh the list after deleting a Todo
this.refresh();
})
}
},
created() {
this.$store.dispatch('loadTodos').then( () => {
// Refresh the list when first loaded after the Todos been saved in Vuex
this.refresh();
})
}
}
</script>
实际上,不要删除已有的东西,而要用它替换,只需将此处的内容应用于代码即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.