Bootstrap4+Thymeleaf中Tab内FullCalendar渲染异常问题求助
问题描述
使用Thymeleaf + Bootstrap 4,在导航标签页(nav-tab)中集成FullCalendar时出现渲染异常:
- 服务器启动后,FullCalendar显示布局错乱
- 调整页面缩放比例后,日历显示恢复正常
相关代码如下:
<!-- fullcalendar 추가부분--> <script src='/fullcalendar/dist/index.global.js'></script> <script> document.addEventListener('DOMContentLoaded', function() { var calendarEl = document.getElementById('calendar'); var calendar = new FullCalendar.Calendar(calendarEl, { editable: false, selectable: false, businessHours: true, dayMaxEvents: true, // allow "more" link when too many events events: [ { title: 'Conference', start: '2023-01-11', end: '2020-09-13' }, { title: 'Meeting', start: '2023-01-12T10:30:00', end: '2023-01-12T12:30:00' }, { title: 'Dinner', start: '2023-01-12T20:00:00' }, { title: 'Birthday Party', start: '2023-01-13T07:00:00' } ] }); calendar.render(); }); </script> <!-- Nav tabs --> <ul class="nav nav-tabs" id="calendarTab"> <li class="nav-item"> <a class="nav-link active" data-toggle="tab" href="#tab1"> <h6 class="m-0 font-weight-bold text-primary">기안문</h6> </a> </li> <li class="nav-item"> <a class="nav-link" data-toggle="tab" href="#tab2"> <h6 class="m-0 font-weight-bold text-primary">연차 달력</h6> </a> </li> </ul> <!-- card-body --> <div class="card-body"> <!-- tab-content --> <div class="tab-content"> <!-- tab-content1 --> <div class="tab-pane active" id="tab1"></div> <!-- tab-content2 --> <div class="tab-pane" id="tab2"> <div id="calendar"></div> </div> </div> </div>
问题原因
FullCalendar初始化时,所在的#tab2标签页处于隐藏状态(Bootstrap的.tab-pane隐藏元素会设置display: none),此时浏览器无法正确计算日历容器的宽高尺寸,导致渲染布局错乱。调整页面缩放时,浏览器触发重绘事件,FullCalendar会重新计算容器尺寸并修正布局,因此显示恢复正常。
解决方案
方案1:切换到目标标签页时再初始化日历
将日历初始化逻辑绑定到标签页的shown.bs.tab事件上,确保只有当#tab2被激活显示后才渲染日历,从根源避免尺寸计算错误:
<script src='/fullcalendar/dist/index.global.js'></script> <script> let calendar = null; document.addEventListener('DOMContentLoaded', function() { // 监听标签页切换完成事件 $('#calendarTab a[data-toggle="tab"]').on('shown.bs.tab', function(e) { const targetTab = $(e.target).attr('href'); // 仅在首次切换到日历标签时初始化 if (targetTab === '#tab2' && !calendar) { const calendarEl = document.getElementById('calendar'); calendar = new FullCalendar.Calendar(calendarEl, { editable: false, selectable: false, businessHours: true, dayMaxEvents: true, events: [ { title: 'Conference', start: '2023-01-11', end: '2020-09-13' }, { title: 'Meeting', start: '2023-01-12T10:30:00', end: '2023-01-12T12:30:00' }, { title: 'Dinner', start: '2023-01-12T20:00:00' }, { title: 'Birthday Party', start: '2023-01-13T07:00:00' } ] }); calendar.render(); } }); }); </script>
方案2:标签页激活时强制更新日历尺寸
如果需要提前初始化日历(比如预加载事件数据),可以在标签页显示时调用FullCalendar的updateSize()方法,强制重新计算容器尺寸:
<script src='/fullcalendar/dist/index.global.js'></script> <script> let calendar = null; document.addEventListener('DOMContentLoaded', function() { const calendarEl = document.getElementById('calendar'); calendar = new FullCalendar.Calendar(calendarEl, { editable: false, selectable: false, businessHours: true, dayMaxEvents: true, events: [ { title: 'Conference', start: '2023-01-11', end: '2020-09-13' }, { title: 'Meeting', start: '2023-01-12T10:30:00', end: '2023-01-12T12:30:00' }, { title: 'Dinner', start: '2023-01-12T20:00:00' }, { title: 'Birthday Party', start: '2023-01-13T07:00:00' } ] }); // 提前初始化日历 calendar.render(); // 标签页显示时更新尺寸 $('#calendarTab a[data-toggle="tab"]').on('shown.bs.tab', function(e) { const targetTab = $(e.target).attr('href'); if (targetTab === '#tab2') { calendar.updateSize(); } }); }); </script>
补充说明
- 确保项目已引入jQuery(Bootstrap的标签页事件依赖jQuery),若使用原生JS,可替换为原生事件监听标签页切换
- 方案1适合无需预加载日历数据的场景,性能更优;方案2适合需要提前加载数据的场景
内容的提问来源于stack exchange,提问作者June
相关产品推荐
相关产品推荐

