From 922b7d3b35f9deee4d0da4a60d43a11ce5f8c65d Mon Sep 17 00:00:00 2001 From: panhuihui <1874909453@qq.com> Date: Thu, 23 Mar 2023 10:26:03 +0800 Subject: [PATCH] =?UTF-8?q?react+ts=E5=90=88=E5=B9=B6=E5=88=B0dev?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/table/table.module.css | 31 +++ src/components/table/table.module.less | 36 ++++ src/components/table/table.tsx | 284 ++++++++++++------------- 3 files changed, 200 insertions(+), 151 deletions(-) create mode 100644 src/components/table/table.module.css create mode 100644 src/components/table/table.module.less diff --git a/src/components/table/table.module.css b/src/components/table/table.module.css new file mode 100644 index 0000000..8e02534 --- /dev/null +++ b/src/components/table/table.module.css @@ -0,0 +1,31 @@ +.content table { + border-collapse: collapse; + width: 100%; +} +.content th, +.content td { + text-align: left; + padding: 8px; +} +.content th { + background-color: #f2f2f2; +} +.content tr:nth-child(even) { + background-color: #f2f2f2; +} +.content tr:hover { + background-color: #ddd; +} +.content td:first-child, +.content th:first-child { + border-left: 1px solid #ddd; +} +.content td:last-child, +.content th:last-child { + border-right: 1px solid #ddd; +} +.content td, +.content th { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; +} diff --git a/src/components/table/table.module.less b/src/components/table/table.module.less new file mode 100644 index 0000000..bfd2b0b --- /dev/null +++ b/src/components/table/table.module.less @@ -0,0 +1,36 @@ +.content{ + table { + border-collapse: collapse; + width:100%; + } + + th, td { + text-align: left; + padding:8px; + } + + th { + background-color: #f2f2f2; + } + + tr:nth-child(even) { + background-color: #f2f2f2; + } + + tr:hover { + background-color: #ddd; + } + + td:first-child, th:first-child { + border-left:1px solid #ddd; + } + + td:last-child, th:last-child { + border-right:1px solid #ddd; + } + + td, th { + border-top:1px solid #ddd; + border-bottom:1px solid #ddd; + } +} \ No newline at end of file diff --git a/src/components/table/table.tsx b/src/components/table/table.tsx index 3fcaf29..7769e3d 100644 --- a/src/components/table/table.tsx +++ b/src/components/table/table.tsx @@ -1,160 +1,142 @@ - -import React, { ReactElement, useMemo, useContext, useState, FormEvent } from 'react'; - -const TableContext = React.createContext<{ - cols: Array, - data: Array, - renderData: Array, - setStore?(store: any): void -}>({ - cols: [], - data: [], - renderData: [], -}); - -export interface IColProps { - key: string; - title: string; - render?(data: any): ReactElement; - sort?: boolean; - screening?: boolean; +import React from "react"; +import styles from "./table.module.less"; +interface Column { + title: string; + dataIndex: string; } -interface ITableProps { - className?: string; - data: Array; - cols: Array +interface Props { + data: any[]; + columns: Column[]; } -export default function Table>(props: ITableProps) { - const { data: OutData, cols: OutCols, className } = props; - - const [store, setStore] = useState({ - cols: OutCols, - renderData: OutData.slice() - }) - - return ( - - - - -
-
- ) +enum SortOrder { + Ascending = "ascend", + Descending = "descend", + None = "none", } -function THead() { - let { cols, data, setStore } = useContext(TableContext) - const [show, setShow] = useState(false) - const [searchInputs, setSearchInputs] = useState>({}) - - const sort = (key: string) => { - // 拷贝一份数据 - const newData = data.slice() - - // 过滤数据 简单排序 - setStore?.((store: any) => ({ - ...store, - renderData: newData.sort((pre, next) => { - const a = pre[key] - const b = next[key] - if (typeof a === 'string' && typeof b === 'string') { - // 如果两个元素都是字符串,则按照字母顺序排序 - return a.localeCompare(b); - } else if (typeof a === 'number' && typeof b === 'number') { - // 如果两个元素都是数字,则按照数值大小排序 - return a - b; - } else { - // 否则,将数字排在字符串的前面 - return typeof a === 'string' ? 1 : -1; - } - }) - })) - } - - const screening = () => { - setShow(!show) - } - - const changeSearchValue = (v: FormEvent, key: string) => { - const keyword = (v.target as HTMLInputElement).value - // 拷贝一份数据 - const newData = data.slice() - // 过滤数据 简单排序 - setStore?.((store: any) => ({ - ...store, - renderData: newData.filter((rowData) => { - return rowData[key].indexOf(keyword) > -1 - }) - })) - - setSearchInputs(prevState => ({ ...prevState, [key]: (v.target as HTMLInputElement).value })) - } - - // 等待性能优化 - const col = useMemo(() => { - const renderSearchInput = (c: IColProps) => { - if (!c.screening || !show) { - return null - } - - return ( - changeSearchValue(e, c.key)} - placeholder="筛选" - /> - ) - } - - return cols?.map(c => { - return - {c?.title} - {c?.sort && } - {c?.screening && } - {renderSearchInput(c)} - - }) - }, [cols, show, searchInputs]) - - return ( - - {col} - - ) +interface State { + sortOrder: SortOrder; + sortColumn: string; + filteredData: any[]; + filterValues: { [key: string]: any }; } -function TBody>() { - const { renderData, cols } = useContext<{ - cols: Array, - data: Array, - renderData: Array, - }>(TableContext) - - const renderTd = (col: IColProps, rowData: RowType) => { - return { - col.render - ? col.render(rowData) - : rowData[col.key] - } - } - - return ( - { - renderData?.map(d => { - return ( - - {cols?.map(c => renderTd(c, d))} - - ) - }) - } - ) +export default class Table extends React.Component { + constructor(props: Props) { + super(props); + + this.state = { + sortOrder: SortOrder.None, + sortColumn: "", + filteredData: props.data, + filterValues: {}, + }; + } + + handleSort = (column: Column) => { + const { dataIndex } = column; + const { sortOrder, sortColumn } = this.state; + + let newSortOrder: SortOrder = SortOrder.Ascending; + if (sortColumn === dataIndex) { + newSortOrder = + sortOrder === SortOrder.Ascending + ? SortOrder.Descending + : SortOrder.Ascending; + } + + let newData = [...this.state.filteredData]; + if (newSortOrder !== SortOrder.None) { + newData = newData.sort((a, b) => + newSortOrder === SortOrder.Ascending + ? a[dataIndex] - b[dataIndex] + : b[dataIndex] - a[dataIndex] + ); + } + + this.setState({ + sortOrder: newSortOrder, + sortColumn: dataIndex, + filteredData: newData, + }); + }; + + handleFilter = (column: Column, value: any) => { + const { dataIndex } = column; + const { filterValues } = this.state; + + const newFilterValues = { ...filterValues, [dataIndex]: value }; + + let newData = [...this.props.data]; + Object.keys(newFilterValues).forEach((key) => { + const filterValue = newFilterValues[key]; + if (filterValue !== null && filterValue !== undefined) { + newData = newData.filter( + (item) => item[key].toString() === filterValue.toString() + ); + } + }); + + this.setState({ + filteredData: newData, + filterValues: newFilterValues, + }); + }; + + render() { + const { columns } = this.props; + const { sortOrder, sortColumn, filteredData, filterValues } = this.state; + + return ( +
+ + + + {columns.map((column) => ( + + ))} + + + + {filteredData.map((item, index) => ( + + {columns.map((column) => ( + + ))} + + ))} + +
+ {column.title} + + +
{item[column.dataIndex]}
+
+ ); + } }