Vuex 更新后强制 props 在子组件中更新
Posted
技术标签:
【中文标题】Vuex 更新后强制 props 在子组件中更新【英文标题】:Force props to update in child component after Vuex update 【发布时间】:2020-12-10 10:45:40 【问题描述】:我有一个子组件 (<BaseProjectTable>
),它在我的整个站点中重复使用,其中包含一个 Vuetify <v-data-table>
组件。数据表的标题和内容项作为 props 传递到组件中,项目数据作为 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
会使数据具有反应性,因此我预计它也会更新我的子组件中的数据,但事实并非如此。
根据我看到的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]
值相比。
我需要做什么才能让数据表显示我更新的值?
【问题讨论】:
active
in store 和 activeProjects
一样吗?无法关联突变 - 我可能在那里错过了一些东西。您是否尝试用this.$set(state[projectType], index, projectData)
替换state[projectType][index] = projectData;
- 这应该确保反应性并反映getter 的变化。
是的(我在上面的代码中添加了吸气剂)。我的问题是我可以在 Vue devtools 中看到我在 getter 中的更改 - 它们只是没有反映在显示中。
【参考方案1】:
来自 Vue documentation,
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)
在此之后,将检测到数组的更改,并且 getter 将按预期工作。
【讨论】:
嗯,在突变中使用Vue.set()
似乎很奇怪,但它确实有效。
Vuex documentation 确认在突变中使用 Vue.set
是合适的。
如果您不介意,请接受答案,以帮助任何偶然发现此页面的人@wonder95以上是关于Vuex 更新后强制 props 在子组件中更新的主要内容,如果未能解决你的问题,请参考以下文章
Vue.js 父子组件,为啥我的 prop 在子组件中还没有?