一、一句话概括原理
先把容器设为不可见(visibility: hidden),让表格在后台完成所有计算、渲染、高度调整;等一切就绪,再瞬间显示出来 —— 用户只看到最终完美状态,看不到中间过程。
二、浏览器渲染视角(为什么用visibility: hidden而不是display: none)
浏览器渲染分四步:
- Parse(解析)→ 生成 DOM
- Style(样式)→ 生成样式树
- Layout(布局 / 回流 / Reflow)→ 计算宽高、位置
- Paint(绘制 / 重绘 / Repaint)→ 画到屏幕上
display: none:在Layout 阶段就被移除,不占空间,切换时会触发回流 + 重绘,容易导致页面抖动。visibility: hidden:Layout 正常计算、保留位置,只在Paint 阶段跳过绘制;切换时只触发重绘、不触发回流,布局完全稳定。
三、你的方案完整流程(为什么 “完全不动”)
- 初始隐藏:外层
div设visibility: hidden,表格在后台开始初始化、计算高度、渲染数据。 - 后台计算:Bootstrap Table 执行
resetView,调整高度、分页、滚动条 ——这一切用户都看不见CSDN博...。 - 统一显示:
resetView完成后,把visibility设为visible,一次性画出最终状态CSDN博...。
四、专业叫法
- 通用叫法:离屏渲染 / 预渲染 / 延迟显式 / 无闪烁渲染
- 前端优化术语:减少布局抖动(Layout Shift)、避免视觉闪烁(Flash of Unstyled Content / FOUC)
- 你这套组合:
visibility: hidden+ 事件触发显式 + 视图重置
五、为什么比setTimeout/shown.bs.modal更稳
setTimeout:时间不可控,可能早了(没算完)、晚了(延迟感)。shown.bs.modal:模态框显示时,表格可能还在计算,依然会闪。- 你这套:等表格完全就绪再显示,是确定性、零抖动的方案。
这个项目有些老,用的是bootstrap table实现的,之前是把height设成350,然后对话框显示出来,点击查询,后来modal又变小了,因为会随着内容的高度来自动调整,感觉怪怪的。
可能的实现:
$("#btn_selCustomer").click(function() { var oTable_customer = new TableInit_customer(); oTable_customer.Init(); $("#myModalLabel_customer").text("选择客户"); $("#myModal_customer").find(".form-control").val(""); $('#myModal_customer').modal(); });不管是对话框先初始化,还是表格先初始化,都是一样,感觉喧染的效果不行。
然后我们使用下面的js将高度拉回来:
$(document).on('shown.bs.modal', function () { $('.modal.in').find('table').each(function () { var $table = $(this); if ($table.data('bootstrap.table')) { $table.bootstrapTable('resetView'); // 视图刷新完再显示,彻底消除闪动 $table.closest('[style*="visibility:hidden"]').css('visibility', 'visible'); } }); });对话框html里的代码:
<div class="row"> <div class="form-group"> <div class="col-sm-12" style="height: 500px;overflow-y: auto;visibility:hidden;"> <table id="tb_customer" data-reorderable-columns="true" style="min-height: 0;height: 500px;"></table> </div> </div> </div>这样就可以了,以下是参考:
离屏渲染技术:弹窗从黑屏到流畅显示的完整解决方案-CSDN博客
这里面写了一些原理,有兴趣可以看一下。