如何在Material UI(v4)表格中实现列宽调整?(函数组件版)
Material UI v4 表格列宽调整(函数组件版)
直接上改写后的函数组件代码,逻辑和你参考的类组件完全一致,适配React函数组件的写法:
import React, { useState, useRef } from 'react'; import { Table, TableHead, TableBody, TableCell, TableRow, Paper } from '@material-ui/core'; const ResizableTable = () => { // 存储各列宽度,替代类组件的state const [columnWidths, setColumnWidths] = useState({ name: 200, calories: 150, fat: 100, carbs: 100, protein: 100, }); // 拖拽相关的引用,替代类组件的实例refs const resizerRefs = useRef({}); const startX = useRef(0); const startWidth = useRef(0); const currentColumn = useRef(null); // 拖拽开始事件 const handleMouseDown = (e, column) => { e.preventDefault(); startX.current = e.clientX; startWidth.current = columnWidths[column]; currentColumn.current = column; document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); }; // 拖拽过程事件 const handleMouseMove = (e) => { if (!currentColumn.current) return; const widthDiff = e.clientX - startX.current; setColumnWidths(prev => ({ ...prev, [currentColumn.current]: Math.max(100, startWidth.current + widthDiff) // 限制最小宽度为100px })); }; // 拖拽结束事件 const handleMouseUp = () => { document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); currentColumn.current = null; }; // 渲染带拖拽手柄的表头单元格 const renderHeaderCell = (label, columnKey) => ( <TableCell style={{ width: columnWidths[columnKey], position: 'relative' }} > {label} <div ref={el => resizerRefs.current[columnKey] = el} style={{ position: 'absolute', right: 0, top: 0, bottom: 0, width: 5, cursor: 'col-resize', backgroundColor: '#ccc', }} onMouseDown={(e) => handleMouseDown(e, columnKey)} /> </TableCell> ); return ( <Paper style={{ width: '100%', overflowX: 'auto' }}> <Table> <TableHead> <TableRow> {renderHeaderCell('Name', 'name')} {renderHeaderCell('Calories', 'calories')} {renderHeaderCell('Fat (g)', 'fat')} {renderHeaderCell('Carbs (g)', 'carbs')} {renderHeaderCell('Protein (g)', 'protein')} </TableRow> </TableHead> <TableBody> <TableRow> <TableCell style={{ width: columnWidths.name }}>Frozen yoghurt</TableCell> <TableCell style={{ width: columnWidths.calories }}>159</TableCell> <TableCell style={{ width: columnWidths.fat }}>6.0</TableCell> <TableCell style={{ width: columnWidths.carbs }}>24</TableCell> <TableCell style={{ width: columnWidths.protein }}>4.0</TableCell> </TableRow> {/* 可自行添加更多数据行 */} </TableBody> </Table> </Paper> ); }; export default ResizableTable;
关键转换说明
- 状态替换:用
useState替代类组件的this.state,直接通过setColumnWidths更新列宽,写法更简洁。 - 引用替换:用
useRef创建拖拽相关的引用(比如起始X坐标、当前拖拽列),代替类组件中createRef生成的实例属性,避免组件重渲染时丢失引用。 - 事件处理:拖拽的三个事件函数直接定义在组件内部,不需要像类组件那样手动绑定
this,借助React闭包就能直接访问状态和引用。 - 渲染逻辑:把表头单元格的渲染抽成
renderHeaderCell函数,和原类组件的渲染逻辑完全对齐,代码结构更清晰。
内容的提问来源于stack exchange,提问作者zahra zamani
相关产品推荐
相关产品推荐

