[英]Vue component doesn't update when state in store is updated
I'm trying to do a simple todo list in Vue but I want to abstract everything out and use a dummy REST API so I can start to get used to production-level projects in Vue and it's all making my head spin. 我试图在Vue中创建一个简单的待办事项清单,但我想抽象出所有内容并使用虚拟的REST API,这样我就可以开始习惯于Vue中的生产级项目,这一切都使我很头疼。 GET, PUT, and POST requests seem to be working, but I can't figure out why the list of todos doesn't update automatically when I do a successful POST request to the back end.
GET,PUT和POST请求似乎可以正常工作,但是当我对后端执行成功的POST请求时,我无法弄清楚为什么待办事项列表不会自动更新。
I've got a TodoList
component that loops through a todosFiltered()
computed property to show the todos. 我有一个
TodoList
组件,该组件遍历todosFiltered()
计算属性以显示todosFiltered()
。 The computed property refers back to the getter todosFiltered
in the Vuex store. 计算出的属性返回到Vuex存储中的getter
todosFiltered
。 I also use the created()
lifecycle hook here to dispatch an action in the store that makes the initial GET request and then populates an array called todos
in the store when the page is first loaded. 我还使用此处的
created()
生命周期钩子在商店中调度一个操作,该操作发出初始GET请求,然后在首次加载页面时在商店中填充一个称为todos
的数组。 The getter todosFiltered
in the store returns state.todos
, so I assumed that when my component re-renders, it would have the new todos
array from the state grabbed from todosFiltered
, only that's not happening. 存储
todosFiltered
中的getter todosFiltered
返回state.todos
,因此我假设当我的组件重新渲染时,它将具有从todosFiltered
抓取的状态中的新todos
数组,只有这种情况没有发生。 What am I missing here? 我在这里想念什么? Any advice would be greatly appreciated.
任何建议将不胜感激。
(I know I'll have to work out a solution for the ids, it's on my list :p) (我知道我必须为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)
})
},
}
})
EDIT: Here's what's going on in Vue Dev Tools when I add a todo -- todos
in the store's state gets updated immediately, and the todosFiltered
computed property in the TodoList
component ALSO reflects that -- but the new todo doesn't appear in the list! 编辑:这是发生了什么事情在Vue的开发工具,当我加入待办事项-
todos
在店内的状态将立即被更新,并且todosFiltered
在计算财产TodoList
分量也反映了-但新的待办事项不会出现在列出! Strange. 奇怪。
The problem is using a $store.getter on the v-for loop. 问题是在v-for循环上使用了$ store.getter。 Try the following:
请尝试以下操作:
Set your computed to 设置您的计算为
todos() { return this.$store.todos; todos(){返回this。$ store.todos; }
}
Change your v-for loop to use todo in todos 更改v-for循环以在待办事项中使用待办事项
Hope this works for you 希望这对你有用
A way to solve this can be to create what I like to call a refresh()
method. 解决此问题的一种方法可以是创建我喜欢调用的
refresh()
方法。
Basically, you will have a local list of todos
in your data()
method, the refresh()
method will load all the todos
from the store into the local todos
list, every time you do an action, such as creating, deleting, or updating, you would call the refresh method to re-load the list for you. 基本上,你将有一个本地列表
todos
在data()
方法中, refresh()
方法将所有负载todos
从商店到本地todos
列表,每次你做一个动作时,如创建,删除或更新后,您将调用refresh方法为您重新加载列表。
So, in your TodoList.vue
: 因此,在您的
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>
Don't actually delete what you already have and replace it with this, just apply what's here to your code.
实际上,不要删除已有的东西,而要用它替换,只需将此处的内容应用于代码即可。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.