You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 12:25:18