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

页面滚动时如何让Material Table水平滚动条始终可见?

React 配合 Material Table 实现常驻水平滚动条(无jQuery依赖)

不需要引入依赖jQuery的floatingScroll插件,通过原生DOM事件绑定+React状态控制就能实现相同效果,核心是做一个和原表格滚动位置双向同步的悬浮滚动条,在页面滚动到对应区间时固定在视口底部显示。

实现逻辑

  • 分别获取Material Table内部原生滚动容器、自定义悬浮滚动条的DOM引用,做双向滚动绑定,保证两者横向滚动位置完全同步
  • 监听页面滚动事件,实时计算表格在视口中的位置,判断是否需要显示悬浮滚动条
  • 监听窗口大小变化、表格数据/列配置更新事件,动态校准悬浮滚动条的可滚动宽度,保证滚动比例和原生表格完全一致
  • 悬浮滚动条固定在视口底部时设置足够高的层级,避免被其他页面元素遮挡

可直接复用的实现代码

import React, { useRef, useEffect, useState } from 'react';
import MaterialTable from 'material-table';

export default function TableWithStickyScroll() {
  const tableWrapperRef = useRef(null);
  const floatingScrollRef = useRef(null);
  const [floatingScrollVisible, setFloatingScrollVisible] = useState(false);
  const [scrollContentWidth, setScrollContentWidth] = useState(0);

  useEffect(() => {
    if (!tableWrapperRef.current) return;
    // 拿到Material Table内置的滚动容器
    const nativeScrollContainer = tableWrapperRef.current.querySelector('.MuiTableContainer-root');
    if (!nativeScrollContainer || !floatingScrollRef.current) return;

    // 初始化滚动区域宽度
    const updateScrollWidth = () => {
      setScrollContentWidth(nativeScrollContainer.scrollWidth);
    };
    updateScrollWidth();

    // 双向同步滚动位置
    const syncNativeScroll = () => {
      floatingScrollRef.current.scrollLeft = nativeScrollContainer.scrollLeft;
    };
    const syncFloatingScroll = () => {
      nativeScrollContainer.scrollLeft = floatingScrollRef.current.scrollLeft;
    };
    nativeScrollContainer.addEventListener('scroll', syncNativeScroll);
    floatingScrollRef.current.addEventListener('scroll', syncFloatingScroll);

    // 页面滚动时控制悬浮条显隐
    const handlePageScroll = () => {
      const containerRect = nativeScrollContainer.getBoundingClientRect();
      // 表格部分滚出视口顶部、且还未完全滚出视口底部时显示悬浮条
      const shouldShow = containerRect.top < 0 && containerRect.bottom > 30;
      setFloatingScrollVisible(shouldShow);
    };

    // 窗口大小变化时重新计算宽度
    const handleResize = () => {
      updateScrollWidth();
      handlePageScroll();
    };

    window.addEventListener('scroll', handlePageScroll);
    window.addEventListener('resize', handleResize);

    return () => {
      nativeScrollContainer.removeEventListener('scroll', syncNativeScroll);
      floatingScrollRef.current.removeEventListener('scroll', syncFloatingScroll);
      window.removeEventListener('scroll', handlePageScroll);
      window.removeEventListener('resize', handleResize);
    };
  }, []);

  return (
    <div ref={tableWrapperRef} style={{ position: 'relative' }}>
      <MaterialTable
        // 此处替换为业务侧的表格配置,包括列定义、数据、操作项等
        title="业务表格"
        columns={[]}
        data={[]}
      />
      {/* 悬浮水平滚动条 */}
      {floatingScrollVisible && (
        <div
          ref={floatingScrollRef}
          style={{
            position: 'fixed',
            bottom: 0,
            left: 0,
            width: '100%',
            height: 20,
            overflowX: 'auto',
            overflowY: 'hidden',
            zIndex: 999,
            background: '#ffffff',
            boxShadow: '0 -2px 6px rgba(0,0,0,0.08)'
          }}
        >
          <div style={{ width: scrollContentWidth, height: 1 }} />
        </div>
      )}
    </div>
  );
}

适配注意事项

  • 如果项目有固定在底部的导航栏/操作栏,可以调整悬浮滚动条的bottom值,避免和固定元素重叠
  • 如果表格存在动态列显隐、滚动加载数据、列宽拖拽调整的场景,要在对应操作完成后调用宽度更新逻辑,保证悬浮滚动条的滚动比例准确
  • 可以根据项目的UI风格调整悬浮滚动条的背景、阴影样式,和整体设计风格保持统一
  • 整个实现不需要引入任何jQuery相关依赖,打包体积远小于直接引入floatingScroll插件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 11:42:17