FullCalendar无法显示Firebase Firestore中事件的问题排查
问题原因
- 非响应式数据:你使用普通数组
events而非Vue 3的响应式ref,导致Firebase异步获取数据后,Vue无法感知数组变化,FullCalendar也就不会重新渲染事件。 - 配置未监听数据变化:
calendarPlugins是普通对象,即便后续events数组内容更新,FullCalendar无法检测到events属性的变化。 - 异步时机偏差:
onMounted中调用getEvents后立即打印events,此时Firebase请求尚未完成,打印的是初始空数组;后续数据加载完成后,数组变化但无响应式通知触发组件更新。
修复步骤
1. 将events改为响应式引用
替换普通数组为Vue的ref,让数据变化能被Vue追踪:
// 替换原有的 let events: any = []; const events = ref<any[]>([]);
2. 修改数据更新方式
ref类型需通过.value访问数组,更新getEvents中的数据推送逻辑:
const getEvents = () => { db.collection("MYEVENT") .get() .then((querySnapshot) => { events.value = []; // 清空旧数据,避免重复加载 querySnapshot.forEach((doc) => { events.value.push({ id: doc.id, title: doc.data().title, description: doc.data().description, start: doc.data().start, end: doc.data().end, backgroundColor: doc.data().backgroundColor, }); }); }); };
3. 让FullCalendar配置绑定响应式数据
直接在calendarPlugins中绑定响应式的events,FullCalendar的Vue组件会自动监听其变化:
const calendarPlugins = { plugins: [dayGridPlugin, timeGridPlugin, interactionPlugin], initialView: "dayGridMonth", headerToolbar: { left: "prev,next,today", center: "title", right: "dayGridMonth,timeGridWeek,timeGridDay", }, editable: true, selectable: true, locale: deLocale, events: events, // 直接绑定响应式ref };
可选:手动刷新事件(兜底方案)
如果上述配置仍未生效,可以通过FullCalendar的API手动触发事件刷新:
- 给FullCalendar添加ref:
<FullCalendar ref="calendarRef" :options="calendarPlugins" />
- 在脚本中定义ref并在获取数据后调用刷新:
const calendarRef = ref<InstanceType<typeof FullCalendar>>(); // 在getEvents的then回调中添加: querySnapshot.forEach((doc) => { /* ...数据推送逻辑... */ }); calendarRef.value?.getApi().refetchEvents();
完整修改后的Calendar.vue代码
<template> <div class="calendar"> <FullCalendar :options="calendarPlugins" /> </div> </template> <script setup lang="ts"> import { db } from "../main"; import { ref, onMounted } from "vue"; import FullCalendar from "@fullcalendar/vue3"; import dayGridPlugin from "@fullcalendar/daygrid"; import timeGridPlugin from "@fullcalendar/timegrid"; import interactionPlugin from "@fullcalendar/interaction"; import deLocale from "@fullcalendar/core/locales/de"; const events = ref<any[]>([]); const testEvent = [ { id: "1", title: "Test", description: "Test", start: "2023-03-03", end: "2023-03-10", backgroundColor: "#1976D2", }, ]; const getEvents = () => { db.collection("MYEVENT") .get() .then((querySnapshot) => { events.value = []; querySnapshot.forEach((doc) => { events.value.push({ id: doc.id, title: doc.data().title, description: doc.data().description, start: doc.data().start, end: doc.data().end, backgroundColor: doc.data().backgroundColor, }); }); }); }; const calendarPlugins = { plugins: [dayGridPlugin, timeGridPlugin, interactionPlugin], initialView: "dayGridMonth", headerToolbar: { left: "prev,next,today", center: "title", right: "dayGridMonth,timeGridWeek,timeGridDay", }, editable: true, selectable: true, locale: deLocale, events: events, }; onMounted(() => { getEvents(); }); </script> <style scoped></style>
额外注意事项
- 确认Firebase返回的
start、end字段为ISO格式字符串(如YYYY-MM-DD或YYYY-MM-DDTHH:mm:ss),FullCalendar才能正确解析时间。 - 检查Firebase的集合权限配置,确保允许前端读取
MYEVENT集合的数据。
内容的提问来源于stack exchange,提问作者Nirwana
相关产品推荐
相关产品推荐

