VueX:如何使用嵌套对象构建我的商店
Posted
技术标签:
【中文标题】VueX:如何使用嵌套对象构建我的商店【英文标题】:VueX: How to architecture my store with nested objects 【发布时间】:2017-09-17 08:36:34 【问题描述】:我目前正在用 VueJS(尤其是 Vuex)编写一个应用程序。但是,我的问题与这个库没有密切的联系,而是与 Flux/redux/Vuex 之类的商店所具有的架构有关。
简单地说,我有几个 API(每个团队一个 API/数据库),对于每个团队/API,我有几个用户。这些团队和用户由简单的对象表示,每个都有自己的 slug。重要提示:团队的 slug 当然是独一无二的,但 slug 用户对于他们自己的团队来说是独一无二的。用户的唯一性约束将是“teamSlug/userSlug”。并且鉴于用户数量众多,我无法简单地加载所有团队的所有用户。
我的问题是如何正确构建我的应用程序/存储以恢复给定用户 slug 的数据(与他的团队):如果我尚未加载此用户,请发出 API 请求以检索它。目前,我创建了一个返回用户对象的 getter,它从用户和团队那里获取 slug。如果它返回“null”或“.loading”为“false”,我必须运行“loadOne”操作来检索它:
import * as types from '../../mutation-types'
import users from '../../../api/users'
// initial state
const state =
users:
// getters
const getters =
getOne: state => (team, slug) => (state.users[team] || )[slug] || null
// actions
const actions =
loadOne ( commit, state , team, slug )
commit(types.TEAM_USER_REQUEST, team, slug )
users.getOne(team, slug)
.then(data => commit(types.TEAM_USER_SUCCESS, team, slug, data ))
.catch(error => commit(types.TEAM_USER_FAILURE, team, slug, error ))
// mutations
const mutations =
[types.TEAM_USER_REQUEST] (state, team, slug )
state.users =
...state.users,
[team]:
...(state.users[team] || ),
[slug]:
loading: true,
error: null,
slug
,
[types.TEAM_USER_SUCCESS] (state, team, slug, data )
state.users =
...state.users,
[team]:
...(state.users[team] || ),
[slug]:
...data,
slug,
loading: false
,
[types.TEAM_USER_FAILURE] (state, team, slug, error )
state.users =
...state.users,
[team]:
...(state.users[team] || ),
[slug]:
slug,
loading: false,
error
export default
namespaced: true,
state,
getters,
actions,
mutations
您想象一个团队不仅有用户,我还有许多其他类型的模型,我应该将它们链接在一起。这种方法有效,但我觉得实施起来相当麻烦(特别是它是一个简单的get,我会有很多其他此类操作)。您对我的架构有什么建议吗?
谢谢!
【问题讨论】:
【参考方案1】:我发现保持 Vuex 存储灵活的最佳方法是对其进行规范化并尽可能保持数据项平坦。这意味着将所有用户存储在一个结构中,并找到一种唯一标识他们的方法。
如果我们将团队和用户 slug 结合起来创建一个唯一标识符会怎样?以下是我想象的红队和蓝队的用户:
const state =
users:
allTeamSlugs: [
'blue1',
'blue2',
'blue3',
'red1',
'red2',
// etc...
],
byTeamSlug:
blue1:
slug: 1,
team: 'blue',
teamSlug: 'blue1'
,
// blue2, blue3, etc...
red1:
slug: 1,
team: 'red',
teamSlug: 'red1'
,
// red2, etc...
并且teamSlug
属性不需要为您的 API 中的每个用户都存在。当您将数据加载到存储中时,您可以在突变中创建它。
const mutations =
[types.TEAM_USER_SUCCESS] (state, team, slug, data )
const teamSlug = [team, slug].join('')
state.users.byTeamSlug =
...state.users.byTeamSlug,
[teamSlug]:
...data,
slug: slug,
team: team,
teamSlug: teamSlug
state.users.allTeamSlugs = [
...new Set([ // The Set ensures uniqueness
...state.users.allTeamSlugs,
teamSlug
])
]
,
// ...
那么你的吸气剂可能会像这样工作:
const getters =
allUsers: state =>
return state.users.allTeamSlugs.map((teamSlug) =>
return state.users.byTeamSlug[teamSlug];
);
,
usersByTeam: (state, getters) => (inputTeam) =>
return getters.allUsers.filter((user) => user.team === inputTeam);
,
getOne: state => (team, slug) => // or maybe "userByTeamSlug"?
const teamSlug = [team, slug].join('');
return state.users.byTeamSlug[teamSlug]; // or undefined if none found
Redux 有一篇关于规范化的精彩文章,我总是发现自己会回到:https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape#designing-a-normalized-state
【讨论】:
以上是关于VueX:如何使用嵌套对象构建我的商店的主要内容,如果未能解决你的问题,请参考以下文章
如何循环遍历传递给具有 Vuex 存储和计算属性的组件的对象数组?
问:使用 Vue 3 和 typescript(使用 cli 构建的项目)使 vuex 存储在全球范围内可用 +已解决