文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

react如何实现表头固定

2023-07-05 00:06

关注

今天小编给大家分享一下react如何实现表头固定的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

react实现表头固定的方法:1、通过Ant Design的Table组件实现表格固定表头;2、使用“rc-table”实现移动端表格表头固定;3、通过监听div的onscroll事件,改变div的scrollLeft属性。

React表格固定表头/锁定列

Ant Design的Table组件挺好用,固定表头及锁定列的功能不在话下,但Ant Design Mobile没有Table组件。移动端要实现表格固定表头及锁定列的功能应该可以使用rc-table,当然也可以自己写一个。

通过分析AntD的Table,可以看出固定表头的表格是由上下两个<table>标签组成的,它们分别嵌套在div内,上面的是表头,只包含<thead>,下边是表格内容,只包含<tbody>。应该是通过监听下面div的onscroll事件,改变上面div的scrollLeft属性,这样在水平滚动表格时,表头也会同步滚动。固定列是通过设置th及td的CSS属性position为sticky并且设置left或right为0实现,同时设置z-index,让锁定的列始终显示在上方。

原理整明白了,写代码就比较容易了。

components/ScrollableTable/interface.tsximport * as React from 'react';export declare type AlignType = 'left' | 'center' | 'right';export interface ColumnType {  align?: AlignType;  className?: string;  dataKey?: string;  fixed?: boolean;  title?: React.ReactNode;  width?: number;  render?: (value: any, record: any, index: number) => React.ReactNode;}export interface TableProps {  className?: string;  style?: React.CSSProperties;  columns?: ColumnType[];  dataSource?: any[];  width?: number;  height?: number;}components/ScrollableTable/index.tsximport React, { FunctionComponent, useRef } from 'react';import { TableProps, ColumnType } from './interface';import './index.less';const ScrollableTable: FunctionComponent<any> = (props: TableProps) => {  const style: React.CSSProperties = props.style || {};  const maxHeight: string = props.width ? (props.height + 'px') : 'unset';  const columns: ColumnType[] = props.columns || [];  const dataSource: any[] = props.dataSource || [];  let maxWidth: number = 0;  if (props.width) style.width = props.width;  if (columns.length === 0) {    columns.push({      dataKey: 'key'    });  }  columns.forEach((column: ColumnType) => {    const width: number = column.width || 50;    maxWidth += width;  });  const fixedColumns: number[][] = getFixedColumns(columns);  const leftFixedColumns: number[] = fixedColumns[0];  const rightFixedColumns: number[] = fixedColumns[1];  const tableBody: any = useRef();  const handleScroll = (target: any) => {    const scrollLeft: number = target.scrollLeft;    const tableHeaders: any = target.parentElement.getElementsByClassName('st-table-header');    if (tableHeaders.length > 0) {      tableHeaders[0].scrollLeft = scrollLeft;    }  };  return (    <div      className={classNames('st-table-container', props.className)}      style={style}    >      <div className="st-table-header">        <table>          <colgroup>            {              renderCols(columns)            }          </colgroup>          <thead className="st-table-thead">            <tr>              {                columns.map((column: ColumnType, index: number) => {                  const align: any = column.align || undefined;                  const title: React.ReactNode = column.title || '';                  const fixed: string = leftFixedColumns.includes(index) ? 'left' : (rightFixedColumns.includes(index) ? 'right' : '');                  const fixedClassName: string = fixed ? ('st-table-cell-fix-' + fixed) : '';                  return (                    <th                      key={index}                      className={classNames('st-table-cell', fixedClassName, column.className)}                      style={{textAlign: align}}                    >                      {title}                    </th>                  );                })              }            </tr>          </thead>        </table>      </div>      <div        ref={tableBody}        className="st-table-body"        style={{maxHeight: maxHeight}}        onScroll={(e: any) => handleScroll(e.currentTarget)}      >        <table style={{width: maxWidth, minWidth: '100%'}}>          <colgroup>              {                renderCols(columns)              }            </colgroup>            <tbody className="st-table-tbody">              {                dataSource.map((record: any, index: number) => (                  <tr key={index} className="st-table-row">                    {                      renderCells(columns, leftFixedColumns, rightFixedColumns, record, index)                    }                  </tr>                ))              }            </tbody>        </table>      </div>    </div>  );};function classNames(...names: (string | undefined)[]) {  const currentNames: string[] = [];  names.forEach((name: (string | undefined)) => {    if (name) currentNames.push(name);  });  return currentNames.join(' ');}function getFixedColumns(columns: ColumnType[]) {  const total: number = columns.length;  const leftFixedColumns: number[] = [];  const rightFixedColumns: number[] = [];  if (columns[0].fixed) {    for (let i = 0; i < total; i++) {      if (columns[i].fixed) {        leftFixedColumns.push(i);      } else {        break;      }    }  }  if (columns[total - 1].fixed) {    for (let i = total - 1; i >= 0; i--) {      if (columns[i].fixed) {        if (!leftFixedColumns.includes(i)) rightFixedColumns.push(i);      } else {        break;      }    }  }  return [leftFixedColumns, rightFixedColumns];}function renderCols(columns: ColumnType[]) {  return columns.map((column: ColumnType, index: number) => {    const width: number = column.width || 50;    return (      <col        key={index}        style={{width: width, minWidth: width}}      />    );  });}function renderCells(columns: ColumnType[], leftFixedColumns: number[], rightFixedColumns: number[], record: any, index: number) {  return columns.map((column: ColumnType, index: number) => {    const align: any = column.align || undefined;    const fixed: string = leftFixedColumns.includes(index) ? 'left' : (rightFixedColumns.includes(index) ? 'right' : '');    const className: string = classNames('st-table-cell', column.className, fixed ? ('st-table-cell-fix-' + fixed) : '');    const rawValue: any = (column.dataKey && column.dataKey in record) ? record[column.dataKey] : undefined;    let value: any = undefined;    if (column.render) {      value = column.render(rawValue, record, index);    } else {      value = (rawValue === undefined || rawValue === null) ? '' : String(rawValue);    }    return (      <td        key={index}        className={className}        style={{textAlign: align}}      >        {value}      </td>    );  });}export default ScrollableTable;components/ScrollableTable/index.less.st-table-container {  border: 1px solid #f0f0f0;  border-right: 0;  border-bottom: 0;  font-size: 14px;  .st-table-header {    border-right: 1px solid #f0f0f0;    overflow: hidden;    table {      border-collapse: separate;      border-spacing: 0;      table-layout: fixed;      width: 100%;      thead.st-table-thead {        tr {          th.st-table-cell {            background: #fafafa;            border-bottom: 1px solid #f0f0f0;            border-right: 1px solid #f0f0f0;            color: rgba(0, 0, 0, .85);            font-weight: 500;            padding: 8px;            text-align: left;            &:last-child {              border-right: 0;            }          }        }      }    }  }  .st-table-body {    overflow: auto scroll;    border-bottom: 1px solid #f0f0f0;    border-right: 1px solid #f0f0f0;    table {      border-collapse: separate;      border-spacing: 0;      table-layout: fixed;      tbody.st-table-tbody {        tr.st-table-row {          td.st-table-cell  {            border-bottom: 1px solid #f0f0f0;            border-right: 1px solid #f0f0f0;            color: rgba(0, 0, 0, .65);            padding: 8px;            text-align: left;            &:last-child {              border-right: 0;            }          }          &:last-child {            td.st-table-cell  {              border-bottom: 0;            }          }        }      }    }  }  table {    .st-table-cell {      &.st-table-cell-fix-left {        background: #fff;        position: sticky;        left: 0;        z-index: 2;      }      &.st-table-cell-fix-right {        background: #fff;        position: sticky;        right: 0;        z-index: 2;      }    }  }}

然后可以这样使用:

views/Test/index.tsximport React, { FunctionComponent } from 'react';import Page from '../../components/Page';import ScrollableTable from '../../components/ScrollableTable';import StoreProvider from '../../stores/products/context';import './index.less';const Test: FunctionComponent<any> = (props: any) => {  let records: any[] = [{    id: 1,    productName: '淡泰',    amount1: 198,    amount2: 200,    amount3: 205.5,    currency: '人民币',    ca: 'Amy'  }, {    productName: '方润',    amount1: 105.5,    amount2: 100,    amount3: 108,    currency: '港元',    ca: 'Baby'  }, {    productName: '医疗基金-1',    amount1: 153,    amount2: 150,    amount3: 155,    currency: '人民币',    ca: 'Emily'  }, {    productName: '医疗基金-2',    amount1: 302,    amount2: 300,    amount3: 290,    currency: '美元',    ca: 'Baby'  }, {    productName: '医疗基金-3',    amount1: 108.8,    amount2: 100,    amount3: 130,    currency: '人民币',    ca: 'Amy'  }, {    productName: '医疗基金-4',    amount1: 205,    amount2: 200,    amount3: 208,    currency: '美元',    ca: '吴丹'  }, {    productName: '医疗基金-5',    amount1: 315.5,    amount2: 300,    amount3: 280,    currency: '人民币',    ca: 'Baby'  }, {    productName: '医疗基金-6',    amount1: 109,    amount2: 95,    amount3: 106,    currency: '人民币',    ca: 'Emily'  }, {    productName: '恒大私募债',    amount1: 213,    amount2: 200,    amount3: 208,    currency: '港元',    ca: '吴丹'  }];  const totalRecord: any = {    productName: '合计',    amount1: {},    amount2: {},    amount3: {}  };  records.forEach((record: any) => {    const currency: string = record.currency;    ['amount1', 'amount2', 'amount3'].forEach((key: string) => {      const value: any = totalRecord[key];      if (!(currency in value)) value[currency] = 0;      value[currency] += record[key];    });  });  records.push(totalRecord);  const columns: any[] = [{    dataKey: 'productName',    title: '产品名称',    width: 90,    fixed: true  }, {    dataKey: 'amount1',    title: <React.Fragment>上周缴款金额<br/>(万)</React.Fragment>,    width: 140,    align: 'center',    className: 'amount',    render: calculateTotal  }, {    dataKey: 'amount2',    title: <React.Fragment>上周预约金额<br/>(万)</React.Fragment>,    width: 140,    align: 'center',    className: 'amount',    render: calculateTotal  }, {    dataKey: 'amount3',    title: <React.Fragment>待本周跟进金额<br/>(万)</React.Fragment>,    width: 140,    align: 'center',    className: 'amount',    render: calculateTotal  }, {    dataKey: 'currency',    title: '币种',    width: 80  }, {    dataKey: 'ca',    title: 'CA',    width: 80  }];  return (    <StoreProvider>      <Page        {...props}        title="销售统计"        className="test"      >        <div style={{padding: 15}}>          <ScrollableTable            width={window.innerWidth - 30}            height={196}            columns={columns}            dataSource={records}          />        </div>      </Page>    </StoreProvider>  );};function calculateTotal(value: any) {  if (value instanceof Object) {    const keys: any[] = Object.keys(value);    return (      <React.Fragment>        {          keys.map((key: string, index: number) => (            <span key={index}>              {`${value[key].toFixed(2)}万${key}`}            </span>          ))        }      </React.Fragment>    )  }  return value.toFixed(2);}export default Test;views/Test/index.less.st-table-container {  .st-table-body {    td.st-table-cell.amount {      padding-right: 20px !important;      text-align: right !important;      span {        display: block;      }    }  }}

以上就是“react如何实现表头固定”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯