我也在开发使用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:由于我只是在未经测试的情况下编写代码,所以代码可能会出现错误,请着眼大图。
好吧,为避免发生以下状态中的意外复杂性,在进行状态归一化时需要注意一些要点。
如官方Redux文档所述
- 每种类型的数据在状态中都有其自己的“表”。
- 每个“数据表”应将单个项目存储在一个对象中,其中项目的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"]
}
}
这样,我们可以确保连接更多的组件并负责查找和维护自己的数据集,而不是每个组件都具有较大的数据集并将数据传递给儿童组件。
更新的答案
由于已经按照组件对数据进行了标准化,因此只需执行一次操作就可以将父组件中的实体传递出去,并且作为标准化的一部分,可以获得以下好处。
- 更快的数据访问,不再需要遍历数组或嵌套对象。
- 组件之间的耦合松动。
- 每个组成部分在商店中都有其自己的位置,因此只有一个真理。
希望这可以帮助!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句