在 Vuex 更新后强制 props 在 child 组件中更新
Force props to update in child component after Vuex update
我的站点中有一个 child 组件 (<BaseProjectTable>
) re-used,其中包含一个 Vuetify <v-data-table>
组件。数据 table 的 headers 和内容项作为 props 传递到组件中,项数据作为 Vuex 存储中的 mapGetter
映射到 parent . child 组件包含每一行的编辑功能,我正在使用 mapAction
从那里更新 API 和 Vuex 数据,因为我的 mapGetter 是反应式的,它应该更新数据并因此更新数据 table 显示。但是,这是行不通的;我可以通过开发工具看到状态更新得很好,但 child 组件显示不是。
这是 child <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])
})
})
},
}
这里是 parent 组件的相关代码:
<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
映射 getter 引用的数据(我已经在 Vue devtools 中验证这是真的)。它还显示组件本身的 items
值在开发工具的 Components
选项卡中更新。由于使用 mapGetters
使数据具有反应性,我预计它也会更新我的 child 组件中的数据,但它没有。
根据我看到的 here,我尝试了 <v-data-table>
的 item-key
属性,如下所示:
<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
键),但这没有用。
我唯一能想到的是我如何在我的突变中编辑数据:
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]
值相比。
我需要做什么才能让数据table显示我的更新值?
来自 Vue documentation,
Vue cannot detect the following changes to an array
- When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue
- When you modify the length of the array, e.g. 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)
}
}
在此之后,将检测到数组的更改,并且 getter 将按预期工作。
我的站点中有一个 child 组件 (<BaseProjectTable>
) re-used,其中包含一个 Vuetify <v-data-table>
组件。数据 table 的 headers 和内容项作为 props 传递到组件中,项数据作为 Vuex 存储中的 mapGetter
映射到 parent . child 组件包含每一行的编辑功能,我正在使用 mapAction
从那里更新 API 和 Vuex 数据,因为我的 mapGetter 是反应式的,它应该更新数据并因此更新数据 table 显示。但是,这是行不通的;我可以通过开发工具看到状态更新得很好,但 child 组件显示不是。
这是 child <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])
})
})
},
}
这里是 parent 组件的相关代码:
<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
映射 getter 引用的数据(我已经在 Vue devtools 中验证这是真的)。它还显示组件本身的 items
值在开发工具的 Components
选项卡中更新。由于使用 mapGetters
使数据具有反应性,我预计它也会更新我的 child 组件中的数据,但它没有。
根据我看到的 here,我尝试了 <v-data-table>
的 item-key
属性,如下所示:
<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
键),但这没有用。
我唯一能想到的是我如何在我的突变中编辑数据:
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]
值相比。
我需要做什么才能让数据table显示我的更新值?
来自 Vue documentation,
Vue cannot detect the following changes to an array
- When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue
- When you modify the length of the array, e.g. 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)
}
}
在此之后,将检测到数组的更改,并且 getter 将按预期工作。