Vue.js 数据更改后未更新的列表和组件-(VueJS+;VueX)

Vue.js 数据更改后未更新的列表和组件-(VueJS+;VueX),vue.js,vuex,Vue.js,Vuex,关于最佳实践的问题(甚至是一个实践) 我有一张清单(例如待办事项清单)。我的实际做法是: 在父组件上,我填充“store.todos”数组。使用 getter,我得到所有要做的事情,并使用v-for在列表上迭代 循环 每个项目都是一个组件,我将待办项目作为道具发送 在这个组件中,我有更新“done”标志的逻辑。这个元素根据标志的“状态”显示一个复选框。当它这样做时,它对数据库执行一个操作并更新存储状态 我是否应该: 让每个列表项都有一个getter,并且只向子组件发送ID 一切正常,但如

关于最佳实践的问题(甚至是一个实践)

我有一张清单(例如待办事项清单)。我的实际做法是:

  • 在父组件上,我填充“store.todos”数组。使用 getter,我得到所有要做的事情,并使用v-for在列表上迭代 循环

  • 每个项目都是一个组件,我将待办项目作为道具发送

  • 在这个组件中,我有更新“done”标志的逻辑。这个元素根据标志的“状态”显示一个复选框。当它这样做时,它对数据库执行一个操作并更新存储状态

我是否应该:

  • 让每个列表项都有一个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);      
        });
    })
}

}
基本上这是我的父组件和子组件:

任务列表组件(它从getter加载任务) (……)


在Vue.js文档之间挖掘之后,我可以修复它

Vue.js和Vuex不会将反应性扩展到不在原始对象上的属性

例如,要在数组中添加新项,必须执行以下操作:

// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
更多信息请点击此处:

在这里:

起初它只解决了部分问题。我不需要在将项目推入数组后使用的“hack”(按下并弹出一个空对象以强制重新加载列表)

但是现在考虑到这一点,我检查了服务器返回的对象,尽管在gettask上,列表包含所有字段,包括完成的_at,但在保存新项后,它只返回设置的字段(创建时完成的_at为null)。这意味着Vue.js没有跟踪此属性

我添加了要由服务器端返回的属性(Laravel,顺便说一句),现在一切正常

如果有人对我的代码有其他看法,请随意添加:)


谢谢各位,我相信Getter的设计完全取决于你们。关于最后一个问题-没有实际的代码很难说。可能您没有为
v-for
元素指定唯一的
key
属性(如果您的意思是更新没有反映在模板中)。@wostex我今天早上尝试了一下,但是运气不好,公平地说,没有正确地完成,因为我一开始没有理解这个概念。我今晚会检查一下,如果问题解决了就告诉你!如果它不能解决您的问题-将您的相关代码部分添加到问题中,这有助于调试。您如何更新“完成”标志-您是否在商店中调用操作?@wostex添加了代码-尝试删除所有不相关的信息以便于检查。。。有趣的是,它可以很好地处理本期已经存在的itemsextra信息,与我的非常相似:
// Vue.set
Vue.set(example1.items, indexOfItem, newValue)