FullCalendar加载3k+任务卡顿问题优化方案求助
FullCalendar 3000条任务数据卡顿优化方案
1. 按需加载事件(核心优化)
不要一次性把所有任务传给FullCalendar,仅渲染当前视图范围内的事件:
- 改用FullCalendar的
events动态函数,在视图切换时自动过滤当前时间段的任务,避免全量渲染 - 修改代码示例:
// 替换原有的calendarOptions.events赋值逻辑 calendarOptions: { //...其他原有配置 events: (info, successCallback) => { // info.start/info.end为当前视图的起止时间 const filteredTasks = this._tasks.filter(task => { const taskStart = new Date(task.date); const taskEnd = task.dueDate ? new Date(task.dueDate) : taskStart; // 判断任务与当前视图时间段是否有交集 return taskEnd >= info.start && taskStart <= info.end; }); // 仅转换过滤后的任务为FullCalendar事件格式 const events = filteredTasks.map(task => { const startDate = formatDateTime(task.date); const endDate = task.dueDate ? formatDateTime(task.dueDate) : undefined; return { title: task.title, extendedProps: { eventId: task.serviceOrderId || task.documentId, }, start: startDate, end: endDate, backgroundColor: this.getEventColor(task), }; }); successCallback(events); } }
- 移除原
setTasks中直接赋值this.calendarOptions.events的逻辑,取消对_tasks的deep监听(改为仅监听数组引用变化)
2. 优化数据监听与转换性能
- 去掉
_tasks的deep: true监听:deep遍历3000条对象的开销极大,改为仅监听数组引用变化,任务更新时通过FullCalendar API刷新事件
// 修改watch配置 watch: { _tasks: { immediate: true, // 移除deep: true handler: function () { this.$refs.calendar.getApi().refetchEvents(); }, }, }
- 缓存日期格式化和事件颜色计算结果:避免重复计算相同任务的日期与颜色
// 组件内添加缓存对象 data() { return { dateFormatCache: new Map(), eventColorCache: new Map() } }, methods: { formatDateTimeCached(dateStr) { if (this.dateFormatCache.has(dateStr)) return this.dateFormatCache.get(dateStr); const formatted = formatDateTime(dateStr); this.dateFormatCache.set(dateStr, formatted); return formatted; }, getEventColorCached(task) { const taskKey = task.serviceOrderId || task.documentId; if (this.eventColorCache.has(taskKey)) return this.eventColorCache.get(taskKey); const color = this.getEventColor(task); this.eventColorCache.set(taskKey, color); return color; } } // 事件转换时替换为缓存方法 const startDate = this.formatDateTimeCached(task.date); const endDate = task.dueDate ? this.formatDateTimeCached(task.dueDate) : undefined; backgroundColor: this.getEventColorCached(task),
3. 减少DOM渲染压力
- 开启单日事件数量限制:当单日事件过多时自动折叠,减少DOM节点数量
calendarOptions: { //...其他配置 eventLimit: true, // 开启折叠 eventLimitText: '更多', // 自定义折叠提示文本 }
- 简化自定义事件模板:避免复杂HTML结构或嵌套组件,降低渲染开销
4. 防抖处理视图更新
- 对事件刷新操作添加防抖,避免快速切换月份时多次触发全量计算
// 引入防抖函数(或自行实现) import { debounce } from 'lodash'; created() { this.debouncedRefetch = debounce(() => { this.$refs.calendar.getApi().refetchEvents(); }, 150); }, watch: { _tasks: { immediate: true, handler: function () { this.debouncedRefetch(); }, }, }
5. 降低响应式追踪开销
- 如果
_tasks仅作为展示数据、无需在组件内修改,可转为非响应式对象,减少Vue的响应式监听开销
methods: { // 在需要处理任务数据时使用 getNonReactiveTasks() { // 通过JSON序列化断开响应式关联 return JSON.parse(JSON.stringify(this._tasks)); } }
内容的提问来源于stack exchange,提问作者user16200753
相关产品推荐
相关产品推荐

