需求:
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:当然我这个 也并不一定 是最好的方法,也不一定就那么全面,我只是 给大家个思路)。
|