Forza l'aggiornamento degli oggetti di scena nel componente figlio dopo l'aggiornamento di Vuex
Ho un componente figlio ( <BaseProjectTable>
) che viene riutilizzato in tutto il mio sito che contiene un <v-data-table>
componente Vuetify . Le intestazioni e gli elementi di contenuto per la tabella dati vengono passati al componente come oggetti di scena ei dati dell'elemento vengono mappati nel genitore come mapGetter
da un negozio Vuex. Il componente figlio contiene funzionalità di modifica per ogni riga e sto usando a mapAction
per aggiornare i dati API e Vuex da lì, con l'idea che poiché il mio mapGetter è reattivo, dovrebbe aggiornare i dati e quindi la visualizzazione della tabella dei dati. Tuttavia, questo non funziona; Posso vedere tramite gli strumenti di sviluppo che lo stato viene aggiornato correttamente, ma la visualizzazione del componente figlio non lo è.
Ecco la parte rilevante del <BaseProjectTable>
componente figlio :
<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])
})
})
},
}
ed ecco il codice pertinente dal componente genitore:
<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'
}),
}
}
Il save()
metodo aggiorna i dati nel mio negozio Vuex a cui fa riferimento il activeProjects
map getter (ho verificato in Vue devtools che questo è vero). Mostra anche il items
valore nel componente stesso aggiornato nella Components
scheda negli strumenti di sviluppo. Poiché l'utilizzo mapGetters
rende i dati reattivi, mi aspettavo che aggiornerà anche i dati nel mio componente figlio, ma non è così.
Sulla base di quello che ho visto qui , ho provato la item-key
proprietà del <in questo v-data-table>
modo:
<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"
>
(ogni record che utilizza questo componente avrà la sow
chiave univoca ), ma non ha funzionato.
L'unico pensiero a cui potrei pensare è come sto modificando i dati nella mia mutazione:
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;
}
}
rispetto alla sostituzione dell'intero state[projectType]
valore.
Cosa devo fare per fare in modo che la tabella dati visualizzi il mio valore aggiornato?
Risposte
Dalla documentazione di Vue ,
Vue non è in grado di rilevare le seguenti modifiche a un array
- Quando imposti direttamente un elemento con l'indice, ad es. Vm.items [indexOfItem] = newValue
- Quando si modifica la lunghezza dell'array, ad esempio vm.items.length = newLength
Sostituisci quello che hai con
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)
}
}
Successivamente, le modifiche all'array verranno rilevate e il getter funzionerà come previsto.