前言
最近在項目中遇到了一個需求,客戶希望表格的列寬可以拖動伸縮。該項目的技術棧是 React + Ant Design 。后來看了文檔后進行了簡單的改動和封裝。以下將使用函數式組件,希望能對各位有所幫助,蟹蟹?(‘ω’)?。
一、業務場景
客戶希望表格的標題欄可以拖動來改變整列的寬窄,為了
向別人裝x
更方便的查看數據多的列,并增加表格組件的交互效果。
二、實現思路
Ant Design 文檔中已經明確給出了類式組件版本的 Demo ,此處在這個示例的基礎上進行修改,改為函數式組件,并對其進行封裝,提高其可復用性。此處奉上 官方文檔地址傳送門 。
三、進行編碼
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小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。