React 之可伸缩列的表格

网友投稿 1066 2022-05-30

前言

最近在项目中遇到了一个需求,客户希望表格的列宽可以拖动伸缩。该项目的技术栈是 React + Ant Design 。后来看了文档后进行了简单的改动和封装。以下将使用函数式组件,希望能对各位有所帮助,蟹蟹٩(‘ω’)و。

一、业务场景

客户希望表格的标题栏可以拖动来改变整列的宽窄,为了

向别人装x

更方便的查看数据多的列,并增加表格组件的交互效果。

二、实现思路

Ant Design 文档中已经明确给出了类式组件版本的 Demo ,此处在这个示例的基础上进行修改,改为函数式组件,并对其进行封装,提高其可复用性。此处奉上 官方文档地址传送门 。

三、进行编码

React 之可伸缩列的表格

1. 安装依赖

首先我们需要安装依赖 react-resizable ,此依赖是实现该拖拽伸缩功能的核心。

# npm 安装 npm install react-resizable --save # yarn 安装 yarn add react-resizable

2. 重写案例

接下来我们将示例的类式写法改为函数式。

// 列表页面 import { useState } from 'react'; import { Table } from 'antd'; import { Resizable } from 'react-resizable';// 核心依赖 import './resizable-title.css';// 此种引入方式不会在类名中添加哈希值,故仅作为替换样式时使用 const ResizableTitle = ({ onResize, width, ...restProps }) => { if (!width) { return () }; return ( { e.stopPropagation() }} /> } onResize={onResize} draggableOpts={{ enableUserSelectHack: false }} > {/* 此处增加行内样式目的:让标题的文字不可选中 */} ); }; const List = () => { // 表格数据 const data = [ { key: 0, date: '2018-02-11', amount: 120, type: 'income', note: 'transfer', }, { key: 1, date: '2018-03-11', amount: 243, type: 'income', note: 'transfer', }, { key: 2, date: '2018-04-11', amount: 98, type: 'income', note: 'transfer', }, ]; // 列配置 const columns = [ { title: 'Date', dataIndex: 'date', width: 200, }, { title: 'Amount', dataIndex: 'amount', width: 100, sorter: (a, b) => a.amount - b.amount, }, { title: 'Type', dataIndex: 'type', width: 100, }, { title: 'Note', dataIndex: 'note', width: 100, }, { title: 'Action', key: 'action', render: () => Delete, } ]; // 用 useState 创建响应式数据 const [cols, setCols] = useState(columns); const colsArray = cols.map((col, index) => { return { ...col, onHeaderCell: column => ({ width: column.width, onResize: handleResize(index) }) }; }); // todo 调整列宽 const handleResize = index => { return (_, { size }) => { const temp = [...cols]; temp[index] = { ...temp[index], width: size.width }; setCols(temp); }; }; return (

); }; export default List;

此处直接使用普通的 CSS ,单独将控制伸缩列的样式放到一个文件中,避免与其他样式代码冲突。页面中其他样式代码可以单独放入同目录下的 index.less ,并用 import styles from './index.less' 方式引入。

/* resizable-title.css */ /* 列表页面 */ .react-resizable-handle { position: absolute; right: -5px; bottom: 0; z-index: 1; width: 10px; height: 100%; cursor: col-resize; }

效果似乎还不错,但是我们接下来还要对其进行封装。

3. 封装复用

为了提高复用性,我们需要把代码封装成一个公共组件。内部使用 Ant Design 的表格 Table 组件。

// components/ResizableTable/index.jsx // 可拖拽表格组件 import { useState } from 'react'; import { Table } from 'antd'; import { Resizable } from 'react-resizable'; import './index.css'; const ResizableTitle = ({ onResize, width, ...restProps }) => { if (!width) { return (

) }; return ( { e.stopPropagation() }} /> } onResize={onResize} draggableOpts={{ enableUserSelectHack: false }} > ); }; const ResizableTable = ({ columns = [], ...props }) => { // * 列数据 const [cols, setCols] = useState(columns); const colsArray = cols.map((col, index) => { return { ...col, onHeaderCell: column => ({ width: column.width, onResize: handleResize(index) }) }; }); // todo 调整列宽 const handleResize = index => { return (_, { size }) => { const temp = [...cols]; temp[index] = { ...temp[index], width: size.width }; setCols(temp); }; }; return ( ); }; export default ResizableTable;

// 列表页面 import ResizableTable from '@/components/ResizableTable';// 可拖拽表格组件 const List = () => { // 表格数据 const data = [ // ... ]; // 列配置 const columns = [ // ... ]; return (

); }; export default List;

/* components/ResizableTable/index.css */ .react-resizable-handle { position: absolute; right: -5px; bottom: 0; z-index: 1; width: 10px; height: 100%; cursor: col-resize; }

4. 组件优化

当然,仅仅封装普通表格 Table 组件是不够的,万一想使用 ProComponents 中的超级表格组件 ProTable 呢。毕竟在后台管理系统中, ProTable 的合理使用可以节省不少开发时间。同时也是为了让该自定义组件更加完善,真正够用且好用。

// components/ResizableTable/index.jsx // 可拖拽表格组件 import { useState } from 'react'; import { Table } from 'antd'; import ProTable from '@ant-design/pro-table'; import { Resizable } from 'react-resizable'; import './index.css'; const ResizableTitle = ({ onResize, width, ...restProps }) => { if (!width) { return (

) }; return ( { e.stopPropagation() }} /> } onResize={onResize} draggableOpts={{ enableUserSelectHack: false }} > ); }; export const ResizableTable = ({ columns = [], ...props }) => { // * 列数据 const [cols, setCols] = useState(columns); const colsArray = cols.map((col, index) => { return { ...col, onHeaderCell: column => ({ width: column.width, onResize: handleResize(index) }) }; }); // todo 调整列宽 const handleResize = index => { return (_, { size }) => { const temp = [...cols]; temp[index] = { ...temp[index], width: size.width }; setCols(temp); }; }; return ( ); }; export const ResizableProTable = ({ columns = [], ...props }) => { // * 列数据 const [cols, setCols] = useState(columns); const colsArray = cols.map((col, index) => { return { ...col, onHeaderCell: column => ({ width: column.width, onResize: handleResize(index) }) }; }); // todo 调整列宽 const handleResize = index => { return (_, { size }) => { const temp = [...cols]; temp[index] = { ...temp[index], width: size.width }; setCols(temp); }; }; return ( ); }; // 默认暴露 普通表格 export default ResizableTable;

// 列表页面 // 可以使用"默认引入"和"模块引入"两种方式,此处使用模块引入方式 import { ResizableTable, ResizableProTable } from '@/components/ResizableTable'; const List = () => { // 表格数据 const data = [ // ... ]; // 列配置 const columns = [ // ... ]; return ( <>

普通表格 ResizableTable:


超级表格 ResizableProTable:

); }; export default List;

小结

本次我们解决了 React 中表格标题行拖动伸缩的问题,同时也进行了公共组件的封装与优化。不积跬步,无以至千里;不积小流,无以成江海。为了更好更强,我们需要不断积累问题的解决方案,才能不断进步。

React web前端

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:MongoDB数据库核心概念
下一篇:HTML5的功能元素
相关文章