我也在使用Vuex开发应用程序,并且遇到了处理嵌套对象会很痛苦的情况,因此我试图尽可能地规范化(扁平化)状态,如下例所示:
users: {
1234: { ... },
46473: { name: 'Tom', topics: [345, 3456] }
},
userList: [46473, 1234]
我的问题是:当您的API响应如下时,实现上述目标的“最佳”方法是什么:
data: [
{id: 'u_0001', name: 'John', coments: [{id: 'c_001', body: 'Lorem Ipsum'}, {...}],
{id: 'u_0002', name: 'Jane', coments: [{id: 'c_002', body: 'Lorem Ipsum'}, {...}],
{...}
]
为了示例,假设comments
是users
的子模块:
选项1:
// action on the user module
export const users = ({ commit, state }, users) => {
commit(SET_USERS, users)
commit('comments/SET_COMMENTS', users)
}
// mutation on the user module
[types.SET_USERS] (state, users) {
state.users = users.reduce((obj, user) => {
obj[user.id] = {
id: user.id,
name: user.name,
comments: user.comments.map(comment => comment.id)
}
return obj
}, {})
state.userIds = users.map(user => user.id)
},
// mutation on the comments module
[types.SET_COMMENTS] (state, users) {
let allComments = []
users.forEach(user => {
let comments = user.comments.reduce((obj, comment) => {
obj[comment.id] = comment
return obj
}, {})
allComments.push(comments)
})
state.comments = ...allComments
},
IMO,此选项很好,因为您不必担心每次更改页面时都会重置状态(SPA / Vue-Router),避免了由于某些原因id: u_001
不再存在的情况,因为每次调用突变时,状态都会被覆盖,但是将users array
传递给两个突变都感觉很奇怪。
选项2:
// action on the user module
export const users = ({ commit, state }, users) => {
// Here you would have to reset the state first (I think)
// commit(RESET)
users.forEach(user => {
commit(SET_USER, user)
commit('comments/SET_COMMENTS', user.comments)
})
}
// mutation on the user module
[types.SET_USER] (state, user) {
state.users[user.id] = {
id: user.id,
name: user.name,
comments: user.comments.map(comment => comment.id)
}
state.userIds.push(user.id)
},
// mutation on the comments module
[types.SET_COMMENTS] (state, comments) {
comments.forEach(comment => {
Vue.set(state.comments, comment.id, comment)
})
state.commentsIds.push(...comments.map(comment => comment.id)
},
在这种情况下,需要重置状态,否则每次离开并重新租用该页面时,您都会得到重复/旧的值。 Wich有点烦人,并且更倾向于错误或行为不一致。
结论 你们如何应对这种情况和建议/最佳实践?答案非常感谢,因为我坚持这些事情。
此外,由于需求并不那么复杂,我也正在尝试避免使用3r方库,例如Vue ORM,normalizr等。
谢谢
PS:由于我只是在未经测试的情况下编写代码,所以该代码可能有错误,请着重注意。
答案 0 :(得分:0)
为了避免在下面的状态中发生意外复杂性,在进行状态归一化时需要注意的重点。
如官方Redux docs
所述
- 每种类型的数据在状态中都有自己的“表”。
- 每个“数据表”都应将单个项目存储在一个对象中,这些项目的ID作为键,而项目本身作为值。
- 对单个项目的任何引用都应通过存储项目的ID来完成。
- ID数组应用于指示顺序。
现在使用上面的示例,从数据中删除冗余。您可以将每个表用于每种信息,例如users
,comments
等。
{
'users': {
byId : {
"user1" : {
username : "user1",
name : "User 1",
},
"user2" : {
username : "user2",
name : "User 2",
},
...
},
allIds : ["user1", "user2", ..]
},
'comments': {
byId : {
"comment1" : {
id : "comment1",
author : "user2",
body: 'Lorem Ipsum'
},
"comment2" : {
id : "comment2",
author : "user3",
body: 'Lorem Ipsum'
},
allIds : ["comment1", "comment2"]
}
}
这样做,我们可以确保连接更多的组件并负责查找和维护自己的数据集,而不是每个组件都具有较大的数据集并将数据传递给儿童组件。
更新后的答案
由于数据已按照组件进行规范化,因此只需执行一次操作就可以将父组件中的实体传递出去,并且作为规范化的一部分,可以实现以下好处。
- 更快地访问数据,不再需要遍历数组或嵌套对象。
- 组件之间的松耦合。
- 每个组件在商店中都有自己的位置,因此只有一个真相。
希望这会有所帮助!