antd Table 实现 表格行固定

需求:

antd Table 只有 列固定 和表头固定,但是 我的需求是 行固定 前 三行固定。

实现步骤

方式一、表格固定行(rowClassName 实现)

思路是 :用position: sticky来实现

position: sticky是一个吸顶的效果,滚动时 会固定在顶部

然后借用top 属性 即可 这里注意 top 并不是固定的,因为

 第一行距离顶部 0

第二行 就是 第一行的高度

第三行 就是 第一行和地二行 高度和

最后使用 rowClassName 实现 。判断 其 下标 给 不同的 类名即可。

代码如下:

 jsx代码:

import React, { Component } from 'react';
import { Table } from 'antd';
import "../../assets/index.css";
class Index extends Component {
    constructor(props) {
        super(props)
        this.state = {
            columns: [
                {
                    title: 'Name',
                    dataIndex: 'name',
                    width: 150,
                },
                {
                    title: 'Age',
                    dataIndex: 'age',
                    width: 150,
                },
                {
                    title: 'Address',
                    dataIndex: 'address',
                },
            ],
            data: []

        }
    }

    componentDidMount() {
        const data = [];
        for (let i = 0; i < 100; i++) {
            data.push({
                key: i,
                name: `Edward King ${i}`,
                age: 32,
                address: `London, Park Lane no. ${i}`,
            });
        }
        this.setState({
            data: data
        })
    }

    fixedTop = (record, index) => {
        let top = 0;
        if (index < 3) {
            let name = `fiexdTr${index}`
            return name;
        } else {
            return
        }
    }
    render() {
        const { data, columns } = this.state;
        return (
            <div>
                <Table columns={columns} dataSource={data} pagination={
   
   { pageSize: 50 }} scroll={
   
   { y: 240 }} rowClassName={this.fixedTop} />
            </div>
        );
    }
}

export default Index

css代码:

.fiexdTr0 {
    position: sticky;
    z-index: 100000;
    top: 0;
    background: red
}

.fiexdTr1 {
    position: sticky;
    z-index: 100000;
    top: 54px;
    background: red
}

.fiexdTr2 {
    position: sticky;
    z-index: 100000;
    top: 108px;
    background: red
}

这个是 一个我写的在线的例子 :

表格固定行(rowClassName 实现)-Ant Design Demo -在线案例

这个方法 其实有些 鸡肋,比如 要固定的行数 不固定,那就不适用了 。 

方式二、表格固定行(rowClassName 实现、固定行数 为动态)

思路:

利用 js的方式 :

1.给Table 加一个 id

2.获取 .table body 

3.获取 table body里的tr 合集

4. 就可以 根据 下标 判断 给其 加 样式了(用 cssText,当然 其它属性也可以 比如 setAttribute等等)

需要注意: 必须等表格 渲染完成 再设置 样式,如果 出不来 ,可以加个 定时器 setTimeOut。

不过 在 create-app里 不需要考虑这个 。只有案例 里需要考虑

jsx代码:

import React, { Component } from 'react';
import { Table } from 'antd';

import "../../assets/index.css";
class Index extends Component {
    constructor(props) {
        super(props)
        this.state = {
            columns: [
                {
                    title: 'Name',
                    dataIndex: 'name',
                    width: 150,
                },
                {
                    title: 'Age',
                    dataIndex: 'age',
                    width: 150,
                },
                {
                    title: 'Address',
                    dataIndex: 'address',
                },
            ],
            data: []

        }
    }

    componentDidMount() {
        const data = [];
        for (let i = 0; i < 100; i++) {
            data.push({
                key: i,
                name: `Edward King ${i}`,
                age: 32,
                address: `London, Park Lane no. ${i}`,
            });
        }
        this.setState({
            data: data
        })

    }

   

    fixedTop = (record, index) => {
        let table = document.getElementById("table1"); //获取 tabel dom
        if (table) { //如果 table存在
            let tableBody = table.getElementsByClassName("ant-table-tbody")[0]; //获取 table的 body
            let trs = tableBody.getElementsByTagName("tr"); //获取 table body的 tr合集
            let top = 0; // top值
            if (index < 3) {
                if (index == 0) {
                    top = 0;
                } else {
                    top = index * 54;
                }
                if (trs[index]) { //设置样式
                    trs[index].style.cssText = `position: sticky;z-index: 100000;background: red;top:${top}px;`
                }
            } else {
                return
            }
        }


    }
    render() {
        const { data, columns } = this.state;
        return (
            <div>
                <Table id="table1" columns={columns} dataSource={data} pagination={
   
   { pageSize: 50 }} scroll={
   
   { y: 240 }}
                rowClassName={this.fixedTop} 
                />
            </div>
        );
    }
}

export default Index

这个是 一个我写的在线的例子 : 

表格固定行(rowClassName 实现,固定行为动态)-Ant Design Demo-在线案例

其实这个也是有缺陷的,设置样式 按道理 只用一次就行,使用 rowClassName 就会运行很多次 。

 这个 写法 其实 也有缺陷 就是 tr的高度 不固定 那就 没法实现了。所以 我又优化了一下,使用 js 动态获取 tr的高度(clientHeight 属性) 相加 即可。

  fixedTop = (record, index) => {
        let table = document.getElementById("table1"); //获取 tabel dom
        if (table) { //如果 table存在
            let tableBody = table.getElementsByClassName("ant-table-tbody")[0]; //获取 table的 body
            let trs = tableBody.getElementsByTagName("tr"); //获取 table body的 tr合集
            let top = 0; // top值
            if (index < 3) {
                if (index == 0) {
                    top = 0;
                } else {
                     //  clientHeight 的值 = 元素内容(这里是高度)+上下padding
                     top +=trs[index].clientHeight; // 动态 获取 tr的高度
                }
                if (trs[index]) { //设置样式
                    trs[index].style.cssText = `position: sticky;z-index: 100000;background: red;top:${top}px;`
                }
            } else {
                return
            }
        }


    }

方式三、

思路:在 componentDidMount 里 调用 设置样式的函数 这样的话 性能可能会好一些。

方式二 用rowClassName 这个 会运行 很多次,有多少调条数据 运行 多少次 ,所以 需要优化一下。

下面这个 做了优化 

import React, { Component } from 'react';
import { Table } from 'antd';
import "../../assets/index.css";
class Index extends Component {
    constructor(props) {
        super(props)
        this.state = {
            columns: [
                {
                    title: 'Name',
                    dataIndex: 'name',
                    width: 150,
                },
                {
                    title: 'Age',
                    dataIndex: 'age',
                    width: 150,
                },
                {
                    title: 'Address',
                    dataIndex: 'address',
                },
            ],
            data: []

        }
    }

    componentDidMount() {
        const data = [];
        for (let i = 0; i < 100; i++) {
            data.push({
                key: i,
                name: `Edward King ${i}`,
                age: 32,
                address: `London, Park Lane no. ${i}`,
            });
        }
        this.setState({
            data: data
        }, () => {
            this.fixedTop(3);
        })

    }




    fixedTop = (rowNumber) => { // rowNumber必须是 number类型
        let table = document.getElementById("table1"); //获取 tabel dom
        if (table) { //如果 table存在
            let tableBody = table.getElementsByClassName("ant-table-tbody")[0]; //获取 table的 body
            let trs = tableBody.getElementsByTagName("tr"); //获取 table body的 tr合集
            let top = 0; // top值
            for (var index = 0; index < rowNumber; index++) {
                if (index < rowNumber) {
                    if (index == 0) {
                        top = 0;
                    } else {
                        top = index * 54;
                    }
                    if (trs[index]) { //设置样式
                        trs[index].style.cssText = `position: sticky;z-index: 100000;background: red;top:${top}px;`
                    }
                } else {
                    return
                }
            }

        }
    }
   
    render() {
        const { data, columns } = this.state;
        return (
            <div>
                <Table id="table1" columns={columns} dataSource={data} pagination={
   
   { pageSize: 50 }} scroll={
   
   { y: 240 }}
                />
            </div>
        );
    }
}

export default Index

这个 写法 其实 也有缺陷 就是 tr的高度 不固定 那就 没法实现了。所以 我又优化了一下,使用 js 动态获取 tr的高度(clientHeight 属性) 相加 即可。

fixedTop = (rowNumber) => { // rowNumber必须是 number类型
        let table = document.getElementById("table1"); //获取 tabel dom
        if (table) { //如果 table存在
            let tableBody = table.getElementsByClassName("ant-table-tbody")[0]; //获取 table的 body
            let trs = tableBody.getElementsByTagName("tr"); //获取 table body的 tr合集
            let top = 0; // top值
            for (var index = 0; index < rowNumber; index++) {
                if (index < rowNumber) {
                    if (index == 0) {
                        top = 0;
                    } else {
                        //  clientHeight 的值 = 元素内容(这里是高度)+上下padding
                        top +=trs[index].clientHeight; // 动态 获取 tr的高度
                    }
                    if (trs[index]) { //设置样式
                        trs[index].style.cssText = `position: sticky;z-index: 100000;background: red;top:${top}px;`
                    }
                } else {
                    return
                }
            }

        }
    }

总结:

综上所述一共三种方案:

最好的是 方式三,其次是方式二、最后是方式一

方式一: 缺点 不灵活,如果固定行数 少 可以使用   优点 简单

方式二:缺点  性能略微不好(实际上可以不计,理论上 确实更费性能) 优点  灵活

方式三:缺点 基本没什么缺点  优点 灵活,性能好

所以我推荐 用第三种 。

我写出来只是 给大家一个思路。

思考拓展

如果 你的表格有分页,分页之后 依然需要 固定前三行 。理论上这三种都可以实现 。最好的依然是方式三 。

只不过 方式三 需要 你在 分页器 change事件 里 再调用这个方法 。

方式一、二则 不用 。

我的思路历程是这样的:

1.先实现 基础的 功能 所以我想到 方式一 的写法。

2. 实现了 基础功能 我有考虑其它 因素,比如 行数 并不固定 于是 想出了 动态 设置 样式,也就是方式二。

3. 既然行数 不固定,表格行 高度也可以不固定,所以 就想到 用js 获取 高度 。 也就是方式三的 写法。

我写这个 只是给大家一个思路,一个功能就是这样 不断的完善出来的,要善于思考,考虑需求考虑全面 ,各个方面要 考虑到(ps:当然我这个 也并不一定 是最好的方法,也不一定就那么全面,我只是 给大家个思路)。

猜你喜欢

转载自blog.csdn.net/weixin_44058725/article/details/124432194