Принудительно обновлять реквизиты в дочернем компоненте после обновления Vuex
У меня есть дочерний компонент (<BaseProjectTable>
), который повторно используется на моем сайте, содержащем Vuetify <v-data-table>
составная часть. Заголовки и элементы содержимого для таблицы данных передаются в компонент как реквизиты, а данные элемента отображаются в родительский элемент какmapGetter
из магазина Vuex. Дочерний компонент содержит функции редактирования для каждой строки, и я используюmapAction
для обновления данных API и Vuex оттуда, при этом идея состоит в том, что, поскольку мой mapGetter является реактивным, он должен обновлять данные и, следовательно, отображение таблицы данных. Однако это не работает; С помощью инструментов разработчика я могу видеть, что состояние обновляется нормально, а отображение дочернего компонента - нет.
Вот соответствующая часть ребенка <BaseProjectTable>
составная часть:
<template>
<div>
<v-data-table
show-expand
:headers="headers"
:items="filteredItems"
:search="search"
tem-key="sow"
@click:row="rowClick"
:hide-default-footer="disablePagination"
dense
:disable-pagination="disablePagination"
>
...
</v-data-table>
...
export default {
name: "BaseProjectTable",
props: {
headers: Array,
items: Array,
loggedInUser: Object,
title: String,
max2chars: v => v.length <= 2 || 'Input too long!',
editDialog: false,
showPracticeFilter: {
default: true,
type: Boolean
},
showSEFilter: {
default: true,
type: Boolean
},
showStatusFilter: {
default: true,
type: Boolean
},
projectType: {
type: String,
default: 'active'
},
disablePagination: {
type: Boolean,
default: true
},
},
},
methods: {
...mapActions('projects', {
saveProject: 'saveProject',
}),
save() {
// Update API and store with new data.
this.saveProject({
projectType: this.projectType,
projectData: this.editedItem
})
},
computed: {
statuses() {
return this.projectType === 'active' ? this.activeStatuses : this.oppStatuses;
},
filteredItems() {
return this.items.filter(d => {
return Object.keys(this.filters).every(f => {
return this.filters[f].length < 1 || this.filters[f].includes(d[f])
})
})
},
}
и вот соответствующий код из родительского компонента:
<v-card>
<BaseProjectTable
:headers="headers"
:items="activeProjects"
:loggedInUser="loggedInUser"
title="Active Projects"
:disablePagination=false
></BaseProjectTable>
</v-card>
...
export default {
computed: {
...mapGetters('projects', {
activeProjects: 'activeProjects',
closedProjects: 'closedProjects',
opportunities: 'opportunities'
}),
}
}
В save()
обновляет данные в моем хранилище Vuex, на которые ссылается activeProjects
map getter (я проверил в Vue devtools, что это правда). Он также показываетitems
значение в самом компоненте обновляется в Components
вкладка в инструментах разработчика. Поскольку использованиеmapGetters
делает данные реактивными, я ожидал, что он также обновит данные в моем дочернем компоненте, но это не так.
Основываясь на том, что я здесь увидел, я попробовалitem-key
свойство <v-data-table>
вот так:
<v-data-table
show-expand
:headers="headers"
:items="filteredItems"
:search="search"
item-key="sow"
@click:row="rowClick"
:hide-default-footer="disablePagination"
dense
:disable-pagination="disablePagination"
>
(каждая запись, использующая этот компонент, будет иметь уникальный sow
key), но это не сработало.
Единственное, что я мог подумать, это то, как я редактирую данные в своей мутации:
export const state = () => ({
active: [],
closed: [],
opportunities: [],
})
export const getters = {
activeProjects: state => state.active,
closedProjects: state => state.closed,
opportunities: state => state.opportunities,
}
export const actions = {
saveProject({ commit }, {projectType, projectData}) {
commit(types.SAVE_PROJECT, {projectType, projectData});
}
}
export const mutations = {
[types.SAVE_PROJECT](state, {projectType, projectData}) {
// Get project from state list by sow field.
const index = state[projectType].findIndex(p => p.sow === projectData.sow);
state[projectType][index] = projectData;
}
}
по сравнению с заменой всего state[projectType]
значение.
Что мне нужно сделать, чтобы таблица данных отображала мое обновленное значение?
1 ответ
Из документации Vue,
Vue не может обнаружить следующие изменения в массиве
- Когда вы напрямую устанавливаете элемент с индексом, например vm.items[indexOfItem] = newValue
- Когда вы изменяете длину массива, например vm.items.length = newLength
Замени то, что у тебя есть
import Vue from 'vue'; // this should be at the top level
export const mutations = {
[types.SAVE_PROJECT](state, {projectType, projectData}) {
// Get project from state list by sow field.
const index = state[projectType].findIndex(p => p.sow === projectData.sow);
Vue.set(state[projectType], index, projectData)
}
}
После этого изменения в массиве будут обнаружены, и геттер будет работать должным образом.