我正在尝试从Firestore初始化我的Vuex存储。代码context.commit('SET_ACTIVITIES', acts)
的最后一行是造成错误的原因。我不认为我使用动作是在直接改变状态。我可能会缺少什么?
这是我的Vuex商店:
export default new Vuex.Store({
strict: true,
state: {
activities: []
},
mutations: {
SET_ACTIVITIES: (state, activities) => {
state.activities = activities
},
},
actions: {
fetchActivities: context => {
let acts = []
let ref = db.collection('activities')
ref.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
if(change.type == 'added') {
acts.push({
id: change.doc.id,
name: change.doc.data().name,
day: change.doc.data().day
})
}
})
})
context.commit('SET_ACTIVITIES', acts)
}
}
此外,它给我的错误等于Firestore中的项目数。如果我只做一次提交,为什么要这样做呢?
控制台:
[Vue警告]:监视程序的回调发生错误“ function(){return this._data。$$ state}”:“错误:[vuex]不在变异处理程序之外变异vuex存储状态。”
和
Error: [vuex] do not mutate vuex store state outside mutation handlers.
at assert (vuex.esm.js?2f62:87)
at Vue.store._vm.$watch.deep (vuex.esm.js?2f62:763)
at Watcher.run (vue.runtime.esm.js?2b0e:4562)
at Watcher.update (vue.runtime.esm.js?2b0e:4536)
at Dep.notify (vue.runtime.esm.js?2b0e:730)
at Array.mutator (vue.runtime.esm.js?2b0e:882)
at eval (store.js?c0d6:36)
at eval (index.cjs.js?e89a:21411)
at eval (index.cjs.js?e89a:4904)
at LLRBNode.inorderTraversal (index.cjs.js?e89a:1899)
答案 0 :(得分:1)
您遇到了对象引用和异步方法的问题。
CollectionReference#onSnapshot()
是异步的,在QuerySnapshot
事件上触发快照侦听器/观察器。
基本上,代码中发生的事情是,在您的突变中将空数组acts
分配给state.activities
(相同的对象引用),然后稍后在您的快照中事件处理程序,直接将元素推入其中。
一种快速的解决方案是在onSnapshot
观察者内部进行突变
fetchActivities: context => {
let ref = db.collection('activities')
ref.onSnapshot(snapshot => {
let acts = []
snapshot.docChanges().forEach(change => {
if(change.type == 'added') {
acts.push({
id: change.doc.id,
name: change.doc.data().name,
day: change.doc.data().day
})
}
})
context.commit('SET_ACTIVITIES', acts)
})
}
如果只想对集合数据进行初始获取,请改用CollectionReference#get()
。鉴于它返回了一个承诺,您可以使用它来执行您的操作composable
async fetchActivities ({ commit }) {
let snapshot = await db.collection('activities').get()
let acts = snapshot.docChanges().filter(({ type }) => type === 'added')
.map(({ doc }) => ({
id: doc.id,
name: doc.data().name,
day: doc.data().day
}))
commit('SET_ACTIVITIES', acts)
}