• react中获取dom元素的高度(table铺满屏幕剩余高度)


    背景

    使用antd写了一个table,为了交互上友好;要求如下

    1. 下图红色区域铺满屏幕剩余高度;
    2. table高度不限,有纵向滚动条;
    3. 页面不允许出现纵向滚动条;
      在这里插入图片描述

    全量demo地址


    知识剖析

    1. 要求1和要求3是同时实现的,只要table铺满屏幕剩余高度即可
    2. 要求2的纵向滚动是通过antd-table的scroll属性实现的,只需要把y的值设置为屏幕剩余高度即可
    3. 那现在的关键就是如何获取屏幕剩余高度了
    4. 屏幕剩余高度=100vh(视窗高度)-header-面包屑-Tab-操作区-间距;如下图
      在这里插入图片描述

    编码实战

    方案 A 原生js获取高度( Dom)

    • 原理:视窗高度依次减去各模块高度;
    • 优点:简单易懂;
    • 缺点:变量过多,略微繁琐;

    核心方法:

    export const getResidueHeightByDom = () => {
      const bodyHeight = document.body.offsetHeight; // 网页可见区域高 (包括边线的高)
      const headerHeight = 64; // header高度
      const breadcrumbHeight = 36 + 16 * 2; // 面包屑高度(包括间距)
      const tabHeight = 46 + 16; // tab高度(包括间距)
      const actionHeight = (document.getElementById('action') as HTMLElement).offsetHeight; // 操作区域高度
      const actionMarginBottomHeight = 16; // 操作区域-底部外边距
      const tableHeaderHeight = 55; // table-表头高度
      const paginationHeight = 32 + 16 * 2; // 分页器高度(包括间距)
      const contentBottomPadding = 24; // content区域的底部padding
      const tabContentTopPadding = 24; // tab子元素区域上padding
      const tabContentBottomPadding = 24; // tab子元素区域下padding
      const residueHeight =
        bodyHeight -
        headerHeight -
        breadcrumbHeight -
        tabHeight -
        actionHeight -
        tableHeaderHeight -
        actionMarginBottomHeight -
        paginationHeight -
        contentBottomPadding -
        tabContentTopPadding -
        tabContentBottomPadding;
      window.console.log('Dom-residueHeight', residueHeight);
      return residueHeight;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    Demo:

    demo地址

    原生js获取高度

    方案 B js 原生(DOMRect)

    • 原理:视窗高度-table 距离顶部距离-底部元素高度-底部间距;

    • 优点:变量较少(方案 A 的优化版);

    • 缺点:只能在页面级别生效;

    核心方法:

    export const getResidueHeightByDOMRect = () => {
      const bodyHeight = document.body.offsetHeight; // 网页可见区域高 (包括边线的高)
      const tableBodyTop = document
        .getElementsByClassName('ant-table-body')[0]
        .getBoundingClientRect().top; // tableBody距离顶部距离
      const paginationHeight = 32 + 16 * 2; // 分页器高度(包括间距);
      const tabContentBottomPadding = 24; // tab子元素区域下padding
      const contentBottomPadding = 24; // content区域的底部padding
      const residueHeight =
        bodyHeight - tableBodyTop - paginationHeight - contentBottomPadding - tabContentBottomPadding;
      window.console.log('DOMRect-residueHeight', residueHeight);
      return residueHeight;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Demo:

    demo地址

    原生js获取高度

    方案 C React-Ref(ref)

    • 原理:视窗高度-table 距离顶部距离-底部元素高度-底部间距;

    • 优点:变量较少(方案 A 的优化版);

    • 缺点:只能在页面级别生效;

    核心方法:

    export const getResidueHeightByRef = (ele: HTMLElement) => {
      const bodyHeight = document.body.offsetHeight; // 网页可见区域高 (包括边线的高)
      const tableHeaderHeight = 55; // table-表头高度
      const tableBodyTop = ele.getBoundingClientRect().top; // tableBody距离顶部距离
      const paginationHeight = 32 + 16 * 2; // 分页器高度(包括间距);
      const tabContentBottomPadding = 24; // tab子元素区域下padding
      const contentBottomPadding = 24; // content区域的底部padding
      const residueHeight =
        bodyHeight -
        tableHeaderHeight -
        tableBodyTop -
        paginationHeight -
        contentBottomPadding -
        tabContentBottomPadding;
      window.console.log('Ref-residueHeight', residueHeight);
      return residueHeight;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    Demo:

    demo地址


    拓展阅读

    layout 根据 Sider 的个数动态追加了".ant-layout-has-sider"类名,导致子组件挂载时获取不到正确的布局信息

    解决方案: 不依赖组件的状态更新hasSider字段,给 组件 添加属性 hasSider

    antd-layout 源码

    ...
    const [siders, setSiders] = React.useState<string[]>([]);
    
      const { prefixCls, className, children, hasSider, tagName: Tag, ...others } = props;
      const classString = classNames(
        prefixCls,
        {
          [`${prefixCls}-has-sider`]: typeof hasSider === 'boolean' ? hasSider : siders.length > 0,
          [`${prefixCls}-rtl`]: direction === 'rtl',
        },
        className,
      );
      ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    参考资料

  • 相关阅读:
    excel中的引用与查找函数篇3
    2022牛客多校(三)
    bootstrap多次上传文件
    Java 中的线程池
    Linux- 僵尸进程(Zombie Process)
    Spring Boot - devtools 热部署
    基于FPGA的VGA图像显示
    使用.net 构建 Elsa Workflow
    Cy3-PEG-SH,Cy3-聚乙二醇-巯基/硫醇,Thiol/SH-PEG-Cy3
    什么是SDN?用一篇文章彻底讲明白 SDN 软件定义网络是什么!
  • 原文地址:https://blog.csdn.net/tianxintiandisheng/article/details/126225128