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

Bootstrap标签页点击时销毁FullCalendar避免重复初始化问题

解决FullCalendar在Bootstrap标签页重复创建及销毁报错问题

问题分析

你遇到的两个核心问题:

  1. 重复创建日历叠加显示:每次点击标签页都会调用calendar_view_session函数,每次都新建一个FullCalendar实例,没有清理旧实例。
  2. 销毁方法报错:$("#calendar").destroy()是错误用法——FullCalendar v4及以上版本是原生JavaScript库,不是jQuery插件,destroy方法属于Calendar实例本身,而非jQuery元素的方法,直接调用jQuery对象的destroy会抛出类型错误。

解决方案

我们可以通过保存日历实例引用+利用Bootstrap标签页的显示事件来解决这两个问题,同时优化性能。

方案1:销毁旧实例后重建(适合需要动态更新配置的场景)

  1. 在app对象中添加实例存储属性:用来保存当前的Calendar实例,方便后续销毁。
  2. 修改calendar_view_session函数:先检查是否存在旧实例,存在则销毁,再创建新实例。
  3. 替换点击事件为Bootstrap标签页的shown.bs.tab事件:避免重复点击触发多次初始化,同时确保日历在元素显示后再渲染(解决隐藏元素渲染尺寸异常问题)。

修改后的代码如下:

JavaScript部分
// 在app对象初始化时添加实例存储属性
app.calendarInstance = null;

calendar_view_session: function(){ 
    // 销毁已存在的日历实例
    if (app.calendarInstance) {
        app.calendarInstance.destroy();
        app.calendarInstance = null;
    }

    var calendarEl = document.getElementById('calendar'); 
    var calendar = new FullCalendar.Calendar(calendarEl, { 
        plugins: [ 'dayGrid', 'timeGrid', 'list', 'interaction' , 'momentTimezone' ], 
        header: { 
            left: 'prev,next today', 
            center: 'title', 
            right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek' 
        }, 
        defaultDate: '2019-04-12', 
        navLinks: true, 
        editable: false, 
        eventLimit: true, 
        events: function(info, successCallback,failureCallback) { 
            var date1 = new Date(info.start.valueOf()); 
            var date2 = new Date(info.end.valueOf()); 
            var callData = { 
                from_date:moment.tz(date1, timeZone).format('YYYY-MM-DD'), 
                to_date: moment.tz(date2, timeZone).format('YYYY-MM-DD') 
            } 
            sessionCalendar = []; 
            $.ajax({ 
                url:app.createApiPath(apiController_data,apiAction_data), 
                method:"POST", 
                dataType: "json", 
                data: { 
                    callData: JSON.parse(JSON.stringify(callData)), 
                    api_version: 1, 
                    deviceType: 'web' 
                }, 
                success: function(responseData){ 
                    successCallback(app.calendarParse(responseData.data.results)); 
                } 
            }) 
        }, 
    }); 
    calendar.render(); 
    // 保存实例到app对象,方便后续销毁
    app.calendarInstance = calendar;
},

// 监听Bootstrap标签页显示事件
$(document).ready(function() {
    $('#calendar_view_session_id').on('shown.bs.tab', function () {
        app.calendar_view_session();
    });
});
HTML部分(移除onclick事件)
<div> 
    <!-- Nav tabs --> 
    <ul class="nav nav-tabs" role="tablist"> 
        <li role="presentation" class="active"><a href="#list_view_session" aria-controls="list_view_session" role="tab" data-toggle="tab">List View</a></li> 
        <li role="presentation"><a href="#calendar_view_session" id="calendar_view_session_id" aria-controls="calendar_view_session" role="tab" data-toggle="tab">Calendar View</a></li> 
    </ul> 
    <!-- Tab panes --> 
    <div class="tab-content"> 
        <div role="tabpanel" class="tab-pane active" id="list_view_session"> 
            <div class="session_list"> 
                <div class="loaderapi hide"> 
                    <i class="fa fa-spinner fa-spin fa-4x" aria-hidden="true"></i> 
                </div> 
            </div> 
        </div> 
        <div role="tabpanel" class="tab-pane" id="calendar_view_session"> 
            <div id='calendar'></div> 
        </div> 
    </div> 
</div>

方案2:仅初始化一次,显示时更新尺寸(性能更优)

如果你的日历配置不需要动态修改,推荐这种方式——只初始化一次日历,每次标签页显示时更新尺寸即可,避免重复销毁重建:

// 全局或app对象中存储日历实例
app.calendarInstance = null;

$(document).ready(function() {
    // 初始化日历(但不立即渲染,因为元素处于隐藏状态)
    var calendarEl = document.getElementById('calendar'); 
    app.calendarInstance = new FullCalendar.Calendar(calendarEl, { 
        // 你的日历配置...
    }); 

    // 监听标签页显示事件
    $('#calendar_view_session_id').on('shown.bs.tab', function () {
        // 第一次显示时渲染日历,之后每次显示更新尺寸
        if (!app.calendarInstance.rendered) {
            app.calendarInstance.render();
        } else {
            app.calendarInstance.updateSize();
        }
    });
});

关键说明

  • FullCalendar实例的销毁:必须调用Calendar实例的destroy()方法,而非jQuery元素的方法,这是v4+版本的重要变化(之前的jQuery版本是$('#calendar').fullCalendar('destroy'))。
  • Bootstrap标签页事件:使用shown.bs.tab而非show.bs.tab,确保标签页完全显示后再操作日历,避免因元素隐藏导致的渲染尺寸异常。

内容的提问来源于stack exchange,提问作者Santosh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:38:32