Cara melaksanakan pengepala jadual tetap dalam React: 1. Laksanakan pengepala jadual tetap melalui komponen Jadual Ant Design 2. Gunakan "rc-table" untuk melaksanakan pengepala jadual tetap pada terminal mudah alih; acara onscroll, tukar atribut scrollLeft div.
Persekitaran pengendalian tutorial ini: Sistem Windows 10, bertindak balas versi 18.0.0, komputer Dell G3.
Bagaimana untuk membetulkan pengepala dalam tindak balas?
Lajur tetap/lajur terkunci jadual tindak balas
Komponen Jadual Ant Design sangat mudah digunakan Ia mempunyai fungsi pengepala tetap dan lajur berkunci, tetapi Ant Design Mobile tidak mempunyai Komponen meja. Untuk melaksanakan fungsi pengepala jadual tetap dan lajur terkunci pada terminal mudah alih, anda sepatutnya boleh menggunakan rc-table, atau sudah tentu anda boleh menulisnya sendiri.
Dengan menganalisis Jadual AntD, kita dapat melihat bahawa jadual dengan pengepala tetap terdiri daripada dua teg Setelah anda memahami prinsipnya, ia akan menjadi lebih mudah untuk menulis kod. Kemudian anda boleh menggunakannya seperti ini: Pembelajaran yang disyorkan: "tutorial video bertindak balas" Atas ialah kandungan terperinci Bagaimana untuk mencapai penetapan pengepala jadual dalam tindak balas. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!components/ScrollableTable/interface.tsx
import * 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.tsx
import 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.tsx
import 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;
}
}
}
}