如何通过Vuex 4向Firebase添加数据?代码报错求助
问题描述
尝试通过Vuex 4实现向Firebase添加和获取数据的功能,但遇到以下问题:
- store.js中除登录代码和
setAuthIsReady外,其余函数均无法正常工作 - 保留添加和更新数据的代码时,页面无法加载,注释掉这些代码后页面才能正常显示
提供的store.js代码
const auth = getAuth() const db = getFirestore() const colRef = collection(db, 'profile') getDocs(colRef) .then((snapshot) => { let profile = [] snapshot.docs.forEach((doc)=>{ profile.push({...doc.data(), id:doc.id }) }) console.log(profile) }) .catch(err =>{ console.log(err.message) }) const addProfileForm = document.querySelector('.add') addProfileForm.addEventListener('submit', (e)=>{ e.preventDefault() addDocs(colRef, { name:addProfileForm.name.value, course:addProfileForm.course.value, reg:addProfileForm.reg.value, phone:addProfileForm.phone.value, }) .then(()=>{ addProfileForm.reset() }) }) const updateProfileForm = document.querySelector('.add') updateProfileForm.addEventListener('submit', (e)=>{ e.preventDefault() } export { auth, getFirestore, collection, getDocs, addDocs }
提供的Vue组件代码
<template> <div class="q-pa-md"> <q-layout view="hHh Lpr lff" > <q-header elevated class="bg-black"> <q-toolbar class="bg-blue"> <q-btn flat @click="drawer = !drawer" round dense icon="menu" /> </q-toolbar> </q-header> <q-card style="max-width: 300px"> <q-drawer v-model="drawer" show-if-above :mini="miniState" @mouseover="miniState = false" @mouseout="miniState = true" mini-to-overlay :width="200" :breakpoint="500" bordered class="bg-grey-3" > <q-scroll-area class="fit"> <q-list padding> <q-item clickable v-ripple> <q-item-section avatar> <router-link style="text-decoration:none;" to="/home"> <q-icon name="home" color="blue" /> </router-link> </q-item-section> <q-item-section> <router-link style="text-decoration:none;" to="/home"> Home </router-link> </q-item-section> </q-item> <q-item clickable v-ripple> <q-item-section avatar> <router-link style="text-decoration:none;" to="/dash"> <q-icon name="dashboard" color="blue" /> </router-link> </q-item-section> <q-item-section> <router-link style="text-decoration:none;" to="/dash"> Dashboard </router-link> </q-item-section> </q-item> <q-item active clickable v-ripple> <q-item-section avatar> <router-link to="/notes"> <q-icon color="blue" name="books" /> </router-link> </q-item-section> <q-item-section> <router-link style="text-decoration:none;" to="/notes"> Notes </router-link> </q-item-section> </q-item> <q-item active clickable v-ripple> <q-item-section avatar> <router-link to="/"> <q-icon @click="handleClick" color="blue" name="logout" /> </router-link> </q-item-section> <q-item-section> <router-link @click="handleClick" style="text-decoration:none;" to="/"> Sign Out </router-link> </q-item-section> </q-item> </q-list> </q-scroll-area> </q-drawer> </q-card> <q-page-container> <q-page > <q-card class="my-card"> <q-card-section horizontal> <q-img class="col-2" src="../assets/uni.png" /> </q-card-section> <q-card-section> <h3>News/Events</h3> <p>Cat 1 will be commenced on Novmber 28 <br/> 2022 </p> <q-btn label="View Timetable" color="primary" rounded @click="timetable = true" /> <q-dialog v-model="timetable"> <q-card class="my-prof lt-xl"> <q-card-section> <div class="text-h6">Timetable</div> </q-card-section> <img :src="time"> <q-card-section class="q-pt-none"> </q-card-section> <q-card-actions align="right" class="text-primary"> <q-btn flat label="Close" v-close-popup /> </q-card-actions> </q-card> </q-dialog> </q-card-section> </q-card> <div class="q-pa-md row items-start q-gutter-md"> <q-card class="my-cad"> <q-card-section class="bg-orange"> <div class="row no-wrap items-center"> <div class="col text-h6 ellipsis font-weight-bold"> Payments Details </div> </div> </q-card-section> <q-card-section class="q-pt-none bg-orange"> <div class="text-caption text-black "> All fees are paid in this account number:<br /> Account Number: 20510018688 <br/> Account Name: DMI and Collaborators Trust<br/> </div> </q-card-section> </q-card> <q-card class="my-cad bg-blue"> <q-card-section > <div class="row no-wrap items-center"> <div class="col text-h6 ellipsis font-weight-bold"> Assignments </div> </div> </q-card-section> <q-card-section class="q-pt-none"> <div class="text-caption text-black "> All assignments are provided by a respective lecturer<br/> To view your progress click below </div> </q-card-section> <q-card-actions align="right"> </q-card-actions> </q-card> <q-card class="my-cad bg-green"> <q-card-section> <div class="row no-wrap items-center"> <div class="col text-h6 ellipsis font-weight-bold"> Results </div> </div> </q-card-section> <q-card-section class="q-pt-none"> <div class="text-caption text-black "> Results are provided at each end of semister. <br/> </div> </q-card-section> </q-card> </div> </q-page> </q-page-container> </q-layout> </div> </template> <script> import { computed, ref } from 'vue' import uni from '../assets/uni.png' import time from '../assets/time.jpg' import { useStore } from 'vuex' const store = useStore() const handleClick = () => { store.dispatch('logout') } export default { setup () { return { drawer: ref(false), miniState: ref(true), timetable:ref(false), uni:uni, installment:ref(false), time:time, handleClick, user: computed(()=> store.state.user) } } } </script> <style lang="sass" scoped> .my-cad width: 80% max-width: 330px .my-cre width: 80% max-width: 330px .my-card width: 100% max-width: 1450px </style>
问题排查与修复方案
1. 语法错误(直接导致页面崩溃)
store.js中更新表单的事件监听代码缺少闭合符号,JS解析失败:
// 错误代码 const updateProfileForm = document.querySelector('.add') updateProfileForm.addEventListener('submit', (e)=>{ e.preventDefault() } // 修复后 const updateProfileForm = document.querySelector('.add') updateProfileForm.addEventListener('submit', (e)=>{ e.preventDefault() })
2. DOM操作逻辑错误
store的职责是管理状态,不应直接操作DOM:
- 组件未渲染完成时,
document.querySelector('.add')会返回null,调用addEventListener会报错 - 应把表单事件监听移到Vue组件中,通过Vuex actions处理数据操作
3. Firebase API调用错误
添加文档的方法名错误,addDocs应为addDoc(单数形式):
// 错误代码 addDocs(colRef, { ... }) // 修复后 addDoc(colRef, { ... })
4. 数据未纳入Vuex状态管理
getDocs仅打印数据到控制台,未存入Vuex state,组件无法获取数据
重构后的完整解决方案
重构store.js(遵循Vuex规范)
import { createStore } from 'vuex' import { getAuth, signOut } from "firebase/auth"; import { getFirestore, collection, getDocs, addDoc } from "firebase/firestore"; const auth = getAuth() const db = getFirestore() const colRef = collection(db, 'profile') export default createStore({ state: { user: null, profiles: [] }, mutations: { SET_USER(state, user) { state.user = user }, SET_PROFILES(state, profiles) { state.profiles = profiles } }, actions: { logout({ commit }) { signOut(auth) .then(() => commit('SET_USER', null)) }, async fetchProfiles({ commit }) { try { const snapshot = await getDocs(colRef) const profiles = snapshot.docs.map(doc => ({ ...doc.data(), id: doc.id })) commit('SET_PROFILES', profiles) } catch (err) { console.error(err.message) } }, async addProfile({}, profileData) { try { await addDoc(colRef, profileData) this.dispatch('fetchProfiles') } catch (err) { console.error(err.message) } } }, getters: { getUser: state => state.user, getProfiles: state => state.profiles } })
组件中处理表单与数据操作
在需要添加表单的组件中,添加如下内容:
<template> <!-- 原有组件内容 --> <div class="q-pa-md"> <form class="add" @submit="handleAddProfile"> <input type="text" v-model="formData.name" placeholder="姓名"> <input type="text" v-model="formData.course" placeholder="课程"> <input type="text" v-model="formData.reg" placeholder="注册号"> <input type="text" v-model="formData.phone" placeholder="电话"> <q-btn type="submit" label="添加信息" color="primary" /> </form> </div> </template> <script> import { ref, onMounted } from 'vue' import { useStore } from 'vuex' export default { setup() { const store = useStore() const formData = ref({ name: '', course: '', reg: '', phone: '' }) onMounted(() => { store.dispatch('fetchProfiles') }) const handleAddProfile = (e) => { e.preventDefault() if (!formData.value.name || !formData.value.course) return store.dispatch('addProfile', formData.value) formData.value = { name: '', course: '', reg: '', phone: '' } } const handleClick = () => { store.dispatch('logout') } return { // 原有返回值 formData, handleAddProfile, handleClick, profiles: store.getters.getProfiles } } } </script>
确保Firebase初始化正确
在项目入口文件(如main.js)中配置Firebase:
import { initializeApp } from "firebase/app"; import { getAuth } from "firebase/auth"; import { getFirestore } from "firebase/firestore"; const firebaseConfig = { // 你的Firebase配置信息 }; const app = initializeApp(firebaseConfig); getAuth(app); getFirestore(app);
内容的提问来源于stack exchange,提问作者Revaycolizer
相关产品推荐
相关产品推荐

