数据更改后列表和组件不更新 - (VueJS + VueX)
Lists and Components not updating after data change - (VueJS + VueX)
有关最佳实践(甚至是首选实践)的问题
我有一个清单(例如待办事项清单)。我的实际做法是:
在我的父组件上,我填充了我的 'store.todos' 数组。用一个
getter,我得到所有待办事项并使用 v-for 在列表上迭代
循环.
每个项目都是一个组件,我将待办事项作为道具发送。
在这个组件中,我有更新 "done" 标志的逻辑。并且该元素根据标志的 "state" 显示一个复选框。当它这样做时,它会对数据库执行操作并更新存储状态。
我应该改为:
- 让每个列表项都有一个 getter,并且只将 ID 发送到子组件下?
一切正常,但如果我将新项目添加到待办事项列表,当我将其标记为已完成时,该项目不会更新。我想知道这个问题是否是因为我在子组件
中使用了一个道具而不是 getter
代码:
商店:
const state = {
tasks: []
}
const mutations = {
CLEAR_TASKS (state) {
state.tasks = [];
},
SET_TASKS (state, tasks) {
state.tasks = tasks;
},
ADD_TASK (state, payload) {
// if the payload has an index, it replaces that object, if not, pushes a new task to the array
if(payload.index){
state.currentSpaceTasks[payload.index] = payload.task;
// (1) Without this two lines, the item doesn't update
state.tasks.push('');
state.tasks.pop();
}
else{
state.tasks.push(payload.task);
}
},
SET_TASK_COMPLETION (state, task){
let index = state.tasks.findIndex(obj => obj.id == task.id);
state.tasks[index].completed_at = task.completed_at;
}
}
const getters = {
(...)
getTasks: (state) => (parentId) => {
if (parentId) {
return state.tasks.filter(task => task.parent_id == parentId );
} else {
return state.tasks.filter(task => !task.parent_id );
}
}
(...)
}
const actions = {
(...)
/*
* Add a new Task
* 1st commit add a Temp Task, second updates the first one with real information (Optimistic UI - or a wannabe version of it)
*/
addTask({ commit, state }, task ) {
commit('ADD_TASK',{
task
});
let iNewTask = state.currentSpaceTasks.length - 1;
axios.post('/spaces/'+state.route.params.spaceId+'/tasks',task).then(
response => {
let newTask = response.data;
commit('ADD_TASK',{
task: newTask,
index: iNewTask
});
},
error => {
alert(error.response.data);
});
},
markTaskCompleted({ commit, dispatch, state }, task ){
console.log(task.completed_at);
commit('SET_TASK_COMPLETION', task);
dispatch('updateTask', { id: task.id, field: 'completed', value: task.completed_at } ).then(
response => {
commit('SET_TASK_COMPLETION', response.data);
},
error => {
task.completed_at = !task.completed_at;
commit('SET_TASK_COMPLETION', task);
});
},
updateTask({ commit, state }, data ) {
return new Promise((resolve, reject) => {
axios.patch('/spaces/'+state.route.params.spaceId+'/tasks/'+ data.id, data).then(
response => {
resolve(response.data);
},
error => {
reject(error);
});
})
}
}
基本上这是我的父子组件:
任务列表组件(它从 Getters 加载任务)
(...)
<task :task = 'item' v-for = "(item, index) in tasks(parentId)" :key = 'item.id"></task>
(...)
任务组件显示一个"checkbox"(使用Fontawesome)。并在 checked/unchecked 之间变化,具体取决于 completed_at 是 set/true。
这个程序工作正常:
- 访问任务列表
- 将一项现有项目标记为已完成 - 复选框已选中
此过程失败
- 添加一个新任务(它触发添加任务,它首先添加一个'temporary'项,然后在ajax的return之后,用真实信息更新它(id等..)。虽然它没有 ID,但任务显示加载而不是复选框,并且在更新后它显示复选框 - 这有效!
- 检查新添加的任务 - 它确实发送了请求,它更新了项目和数据库。但是复选框没有更新:(
在 Vue.js 文档之间进行挖掘后,我可以修复它。
Vue.js 并且 Vuex 不会将反应性扩展到不在原始对象上的属性。
例如,要在数组中添加新项目,您必须这样做:
// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
更多信息在这里:
https://vuejs.org/v2/guide/reactivity.html
这里:https://vuejs.org/v2/guide/list.html#Caveats
起初它只解决了部分问题。我不需要在将项目推入数组后使用 "hack"(推入并弹出一个空对象以强制重新加载列表)
但现在考虑到这一点,我检查了服务器返回的对象,虽然在 getTasks 上,列表包含所有字段,包括 completed_at,但在保存新项目后,它是仅返回已设置的字段(completed_at 在创建时为空)。这意味着 Vue.js 没有跟踪这个 属性。
我添加了服务器端返回的 属性(Laravel,顺便说一句),现在一切正常!
如果有人对我的代码有其他意见,请随时添加:)
谢谢大家
有关最佳实践(甚至是首选实践)的问题
我有一个清单(例如待办事项清单)。我的实际做法是:
在我的父组件上,我填充了我的 'store.todos' 数组。用一个 getter,我得到所有待办事项并使用 v-for 在列表上迭代 循环.
每个项目都是一个组件,我将待办事项作为道具发送。
在这个组件中,我有更新 "done" 标志的逻辑。并且该元素根据标志的 "state" 显示一个复选框。当它这样做时,它会对数据库执行操作并更新存储状态。
我应该改为:
- 让每个列表项都有一个 getter,并且只将 ID 发送到子组件下?
一切正常,但如果我将新项目添加到待办事项列表,当我将其标记为已完成时,该项目不会更新。我想知道这个问题是否是因为我在子组件
中使用了一个道具而不是 getter代码:
商店:
const state = {
tasks: []
}
const mutations = {
CLEAR_TASKS (state) {
state.tasks = [];
},
SET_TASKS (state, tasks) {
state.tasks = tasks;
},
ADD_TASK (state, payload) {
// if the payload has an index, it replaces that object, if not, pushes a new task to the array
if(payload.index){
state.currentSpaceTasks[payload.index] = payload.task;
// (1) Without this two lines, the item doesn't update
state.tasks.push('');
state.tasks.pop();
}
else{
state.tasks.push(payload.task);
}
},
SET_TASK_COMPLETION (state, task){
let index = state.tasks.findIndex(obj => obj.id == task.id);
state.tasks[index].completed_at = task.completed_at;
}
}
const getters = {
(...)
getTasks: (state) => (parentId) => {
if (parentId) {
return state.tasks.filter(task => task.parent_id == parentId );
} else {
return state.tasks.filter(task => !task.parent_id );
}
}
(...)
}
const actions = {
(...)
/*
* Add a new Task
* 1st commit add a Temp Task, second updates the first one with real information (Optimistic UI - or a wannabe version of it)
*/
addTask({ commit, state }, task ) {
commit('ADD_TASK',{
task
});
let iNewTask = state.currentSpaceTasks.length - 1;
axios.post('/spaces/'+state.route.params.spaceId+'/tasks',task).then(
response => {
let newTask = response.data;
commit('ADD_TASK',{
task: newTask,
index: iNewTask
});
},
error => {
alert(error.response.data);
});
},
markTaskCompleted({ commit, dispatch, state }, task ){
console.log(task.completed_at);
commit('SET_TASK_COMPLETION', task);
dispatch('updateTask', { id: task.id, field: 'completed', value: task.completed_at } ).then(
response => {
commit('SET_TASK_COMPLETION', response.data);
},
error => {
task.completed_at = !task.completed_at;
commit('SET_TASK_COMPLETION', task);
});
},
updateTask({ commit, state }, data ) {
return new Promise((resolve, reject) => {
axios.patch('/spaces/'+state.route.params.spaceId+'/tasks/'+ data.id, data).then(
response => {
resolve(response.data);
},
error => {
reject(error);
});
})
}
}
基本上这是我的父子组件:
任务列表组件(它从 Getters 加载任务) (...)
<task :task = 'item' v-for = "(item, index) in tasks(parentId)" :key = 'item.id"></task>
(...)
任务组件显示一个"checkbox"(使用Fontawesome)。并在 checked/unchecked 之间变化,具体取决于 completed_at 是 set/true。
这个程序工作正常:
- 访问任务列表
- 将一项现有项目标记为已完成 - 复选框已选中
此过程失败
- 添加一个新任务(它触发添加任务,它首先添加一个'temporary'项,然后在ajax的return之后,用真实信息更新它(id等..)。虽然它没有 ID,但任务显示加载而不是复选框,并且在更新后它显示复选框 - 这有效!
- 检查新添加的任务 - 它确实发送了请求,它更新了项目和数据库。但是复选框没有更新:(
在 Vue.js 文档之间进行挖掘后,我可以修复它。
Vue.js 并且 Vuex 不会将反应性扩展到不在原始对象上的属性。
例如,要在数组中添加新项目,您必须这样做:
// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
更多信息在这里: https://vuejs.org/v2/guide/reactivity.html
这里:https://vuejs.org/v2/guide/list.html#Caveats
起初它只解决了部分问题。我不需要在将项目推入数组后使用 "hack"(推入并弹出一个空对象以强制重新加载列表)
但现在考虑到这一点,我检查了服务器返回的对象,虽然在 getTasks 上,列表包含所有字段,包括 completed_at,但在保存新项目后,它是仅返回已设置的字段(completed_at 在创建时为空)。这意味着 Vue.js 没有跟踪这个 属性。
我添加了服务器端返回的 属性(Laravel,顺便说一句),现在一切正常!
如果有人对我的代码有其他意见,请随时添加:)
谢谢大家