我目前正在构建一个 vue/vuex/firestore/vuexFire 项目,我遇到了以下问题。
假设我想显示一个消息列表,其中每条消息都与一个用户相关联。一个用户可以提交多条消息,这些消息都将在他们的名下。在 vuex 中,它的平面表示可能如下所示:
用户状态模块
state: () => ({
users: [
{
name: 'foo',
id: 'bar'
}
//...
]
})
消息状态模块
state: () => ({
messages: [
{
message: 'blah blah',
authorId: 'bar'
}
//...
]
})
在服务器上(我使用的是 Firebase 的 Firestore),结构基本相同。因此,我获取所有消息,然后像这样关注每个 authorId:
// action in the vuex messages module
{
fetchMessages: async ({ commit, dispatch }) => {
const snapshot = await firestore.collection('messages').get();
snapshot.forEach((doc) => {
// commit the document
commit('addMessage', doc.data())
// fetch the associated user
dispatch('fetchUser', doc.data().authorId)
})
},
fetchUser: async ({commit}, id) => {
const user = await firestore.collection('users').doc(id).get();
commit('addUser', user.data())
}
}
我遇到的问题是,如果有一个用户创建了多条消息,它们将一遍又一遍地添加到 users 数组中。此外,fetchUser()
一遍又一遍地不必要地调用。到目前为止,我解决这个问题的尝试失败或不优雅:
users
我试图在调用之前检查用户是否已经存在于数组中fetchUser()
。但是,这不起作用,因为fetchUser
是异步操作。它可能正在获取过程中,因此检查用户是否已经在数组中通常测试为假。我试图检查用户是否已经存在于
addUser
突变中。虽然这确实可以防止重复,但它并不能防止不必要的用户获取。此外,addUser
突变必须在每次调用时检查用户不是重复的,这对于较大的数组可能会很昂贵。一种有效的方法是在状态中创建一个
fetchJobs
对象users
。当fetchUser()
被调用时,我将用户的 id 添加到对象中。然后,在获取其他用户之前,我会检查此对象以确保我没有获取重复项。与直接检查状态相反,这样做的原因是我在操作开始时提交了 fetchJob,因此它不是异步的。这样,其他组件和状态模块就可以访问它。但是,如果用户对象需要随时更新,这将不起作用,因为它仍将保留在 fetchJobs 对象中。
我还应该提到我正在使用一个名为 VuexFire 的小型帮助程序库,它管理 Firestore 的绑定collectionReference.onSnapshot()
。这引入了另一个限制,即在添加、更新或删除文档时我无法直接运行操作。这是因为 VuexFire 会自动处理所有这些更改,并且不支持挂钩这些事件。相反,我必须遍历所有现有消息并调用fetchUser()
. 我没有在上面的代码示例中包含它,因为它与snapshot.forEach()
. 如果需要,我也可以放弃这个库。
那么,解决这个问题的最佳方法是什么?