应监听 .layui-table-box 元素的原生 scroll 事件,因 Layui table 实例不直接对应可滚动 DOM 节点;需在 render 的 done 回调中查询该容器并绑定事件,重载后须重新绑定。
layui table 横向滚动时如何捕获 scroll 事件
layui 的 table 渲染后,内部实际是两层结构:外层容器(.layui-table-box)包裹着表头(.layui-table-header)和数据体(.layui-table-body),横向滚动条默认出现在 .layui-table-box 上。直接给 table 实例绑 scroll 不生效,因为实例本身不对应可滚动 dom 节点。
正确做法是等表格渲染完成,手动查到该容器并监听其 scroll 事件:
- 必须等
table.render()的done回调执行后操作,此时 DOM 已就位 - 不要用
table.on('event(...)—— 这是 Layui 自定义事件,不包含原生 scroll -
.layui-table-box是唯一带overflow-x: auto的父容器,它是 scroll 事件的实际触发源
table.render({
elem: '#demo',
url: '/api/list',
done: function(res, curr, count) {
// 表格渲染完毕后,查找 .layui-table-box 并监听
const box = document.querySelector('.layui-table-box');
if (box) {
box.addEventListener('scroll', function() {
console.log('横向滚动位置:', this.scrollLeft);
});
}
}
});
为什么 table.on('scroll') 会失效
因为 table.on('scroll') 是 Layui 的事件代理机制,它只处理自己主动 emit 的事件(如 sort、tool、rowDouble),并不代理原生 DOM 事件。你写 table.on('scroll', ...) 实际上什么都不会触发,控制台也无报错,容易误以为“写了但没反应”。
- Layui 的
table.on()底层靠的是layui.onevent(),仅响应layui.event()主动派发的事件 -
scroll是浏览器原生事件,不会被自动收集进 Layui 事件系统 - 即使监听了
document或window,也捕获不到表格内部滚动,因为事件没冒泡出.layui-table-box
监听后怎么判断是否是横向滚动
单纯监听 scroll 事件无法区分横向/纵向滚动,需结合 scrollLeft 和 scrollTop 变化判断。但更稳妥的做法是直接检查 scrollLeft 是否变化,因为 Layui 表格横向滚动时,scrollTop 几乎不变(除非同时有纵向滚动条且用户也在拖拽)。
- 用闭包缓存上一次的
scrollLeft值,对比变化量(避免频繁触发) - 不要依赖
event.target === box判断方向,某些浏览器会在子元素上触发 scroll - 如果表格列很多、内容宽,
scrollLeft可能跳变(比如鼠标滚轮快速滚动),建议加requestAnimationFrame节流
let lastScrollLeft = 0;
box.addEventListener('scroll', function() {
if (this.scrollLeft !== lastScrollLeft) {
lastScrollLeft = this.scrollLeft;
// 这里处理横向滚动逻辑,比如同步固定列、更新状态栏等
}
});
兼容性与重渲染场景下的注意事项
表格重载(table.reload())、切换分页、或动态显示/隐藏列时,.layui-table-box 可能被重建,之前绑定的事件监听会丢失。
- 每次
reload后必须重新查询.layui-table-box并重新绑定 scroll 监听 - 不要在全局作用域一次性绑定——表格可能还没渲染,或已被销毁
- 移动端 Safari 对
scroll事件触发时机较特殊(可能延迟或不触发),若需强响应,可配合touchmove+getBoundingClientRect()粗略估算 - 如果页面有多个 Layui 表格,注意用更精确的选择器(例如加 ID 前缀)避免监听错容器
最麻烦的不是监听本身,而是每次表格结构变动后你得记得手动恢复监听 —— 这个点很容易漏,尤其在封装组件或多人协作时。











