VueX: 중첩된 객체를 사용하여 스토어를 구성하는 방법
현재 VueJs(특히 Vuex)에서 애플리케이션을 코딩하고 있습니다.그러나 제 질문은 이 라이브러리와 강하게 관련되어 있는 것이 아니라 flux/redux/Vuex와 같은 스토어와 함께 가지고 있는 아키텍처와 관련되어 있습니다.
간단히 말하면, 저는 여러 개의 API(팀당 1개의 API/데이터베이스)를 가지고 있으며, 각 팀/API마다 여러 명의 사용자가 있습니다.이 팀들과 사용자들은 단순한 객체로 표현되며, 각각의 팀들은 그들만의 슬러그를 가지고 있다.중요한 주의: 팀의 슬러그는 물론 독특하지만, 슬러그 사용자들은 그들 자신의 팀에게 독특하다.사용자의 고유성 제약은 "teamSlug/userSlug"이 됩니다.게다가 유저가 많은 것을 고려하면, 모든 팀의 유저를 간단하게 로드할 수 없습니다.
제 질문은 주어진 사용자 slug의 데이터를 복구하기 위해 애플리케이션/스토어를 적절하게 설계하는 방법: 이 사용자를 아직 로드하지 않은 경우 API를 요청하여 취득하는 방법입니다.현재 사용자 오브젝트를 반환하는 getter를 만들고 있습니다.이 getter는 사용자와 팀의 slug를 가져갑니다."null"이 반환되거나 ".loading"에서 "false"로 반환된 경우 "load One" 작업을 실행하여 검색 작업을 수행해야 합니다.
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
}
팀에는 사용자만 있는 것이 아니라 다른 유형의 모델도 많기 때문에 이들을 링크해야 합니다.이 방법은 효과가 있지만, 그것을 도입하는 것은 다소 번거롭습니다(특히 단순한 수단이기 때문에, 나는 이러한 종류의 행동을 많이 할 것입니다).제 건축에 대해 조언해 주시겠어요?
감사해요!
Vuex 저장소를 유연하게 유지하는 가장 좋은 방법은 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
])
]
},
// ...
}
그러면 getter는 다음과 같이 동작할 수 있습니다.
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는 정규화에 관한 훌륭한 기사를 게재하고 있습니다.이 기사에는 항상 다시 접속할 수 있습니다.
언급URL : https://stackoverflow.com/questions/43524115/vuex-how-to-architecture-my-store-with-nested-objects
'programing' 카테고리의 다른 글
타이프스크립트:VueX 스토어 모듈을 참조하면 VueJs 2.5에 대한 네임스페이스 오류가 표시됨 (0) | 2022.08.29 |
---|---|
농담으로 vue 합성 함수를 조롱하는 방법 (0) | 2022.08.29 |
lamda 표현식은 실행될 때마다 힙에 개체를 생성합니까? (0) | 2022.08.29 |
C의 이중 포인터 연속성 경고 (0) | 2022.08.29 |
지도에서 반복 제거 (0) | 2022.08.29 |