我目前正在VueJS中编写应用程序(尤其是Vuex)。但是,我的问题与这个库并没有很强的联系,而是与像flux / redux / Vuex这样的商店有关的架构。
简而言之,我有几个API(每个团队一个API /数据库),对于每个团队/ API,我有几个用户。这些团队和用户由简单对象表示,每个都有自己的slug。重要提示:团队的障碍当然是独一无二的,但slu users用户对于他们自己的团队来说是独一无二的。然后,用户的唯一性约束将是" 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
}
您认为团队不仅拥有用户,我还有许多其他类型的模型,我应该将它们链接在一起。这个方法有效,但我发现它很麻烦(特别是它很简单,我会有很多其他类似的动作)。你对我的架构有什么建议吗?
谢谢!
答案 0 :(得分:0)
我发现保持Vuex存储灵活的最佳方法是对其进行规范化并保持数据项尽可能平坦。这意味着将所有用户存储在一个结构中,并找到一种唯一标识他们的方法。
如果我们将团队和用户群结合起来以创建唯一标识符怎么办?这是我如何想象您的用户有一个红色团队和一个蓝色团队的情况:
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...
}
}
}
API中的每个用户都不需要存在teamSlug
属性。您可以在将数据加载到存储区时以自己的突变形式创建它。
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