You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为MUI Table实现类MS Word添加行功能并关联react-hook-form?

MUI Table实现Word式插入行 + react-hook-form关联方案

一、技术选型:直接用MUI就行,别从零写

MUI的Table组件自带成熟的样式体系和交互基础,完全能实现这个需求。从零用原生HTML写的话,你得自己处理悬停样式、按钮对齐、和现有项目UI风格统一这些琐碎事,纯纯浪费时间。用MUI能直接复用现成组件,效率高多了。

二、核心实现步骤

1. 基础框架:MUI Table + react-hook-form FieldArray

先用MUI的Table系列组件搭好表格结构,再用react-hook-form的useFieldArray管理行数据——这玩意儿专门用来处理表单里的动态数组,插入、删除、修改都能自动同步表单状态,省得自己写状态逻辑。

2. 悬停显示加号按钮

给每个TableRow加onMouseEnter和onMouseLeave事件,记录当前悬停的行索引。然后在每行的最左侧放个MUI的IconButton(用Add图标),默认隐藏,只有当该行处于悬停状态时才显示。

3. 点击插入行

点击加号时,调用useFieldArray的insert方法,在当前行的位置(比如下方)插入一条空数据就行,表单状态会自动更新。

三、完整代码示例

import { useState } from 'react';
import { useForm, useFieldArray } from 'react-hook-form';
import { Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Paper, IconButton, Add } from '@mui/material';

export default function InsertRowTable() {
  const { control, register } = useForm({
    defaultValues: {
      rows: [
        { id: 1, name: '默认行1', value: '示例值1' },
        { id: 2, name: '默认行2', value: '示例值2' },
      ],
    },
  });
  const { fields, insert } = useFieldArray({
    control,
    name: 'rows',
  });
  const [hoveredIndex, setHoveredIndex] = useState(null);

  const handleInsert = (index) => {
    // 在当前行下方插入新行,要插上方直接传index就行
    insert(index + 1, { id: Date.now(), name: '', value: '' });
  };

  return (
    <TableContainer component={Paper}>
      <Table>
        <TableHead>
          <TableRow>
            <TableCell sx={{ width: 40 }}></TableCell>
            <TableCell>名称</TableCell>
            <TableCell>值</TableCell>
          </TableRow>
        </TableHead>
        <TableBody>
          {fields.map((row, index) => (
            <TableRow
              key={row.id}
              onMouseEnter={() => setHoveredIndex(index)}
              onMouseLeave={() => setHoveredIndex(null)}
            >
              <TableCell>
                {hoveredIndex === index && (
                  <IconButton
                    size="small"
                    onClick={() => handleInsert(index)}
                    sx={{ opacity: 0.7, transition: 'opacity 0.2s', '&:hover': { opacity: 1 } }}
                  >
                    <Add />
                  </IconButton>
                )}
              </TableCell>
              <TableCell>
                <input
                  {...register(`rows.${index}.name`)}
                  style={{ width: '100%', padding: '4px', border: '1px solid #eee', borderRadius: '4px' }}
                />
              </TableCell>
              <TableCell>
                <input
                  {...register(`rows.${index}.value`)}
                  style={{ width: '100%', padding: '4px', border: '1px solid #eee', borderRadius: '4px' }}
                />
              </TableCell>
            </TableRow>
          ))}
        </TableBody>
      </Table>
    </TableContainer>
  );
}

关键细节说明

  • hoveredIndex用来跟踪当前悬停的行,控制加号按钮的显隐
  • useFieldArray的insert方法直接操作表单数组,不用手动维护状态
  • MUI的IconButton自带点击反馈和样式,加个过渡动画让显示/隐藏更丝滑

四、优化小技巧

  • 插入新行后可以自动聚焦到第一个输入框,用useEffect或者ref实现
  • 表格行数多的话,给TableRow套个React.memo减少不必要的渲染
  • 可以把加号按钮的位置调整到行的右侧,或者根据你的UI需求自定义样式

内容的提问来源于stack exchange,提问作者Ákos Dániel Bollók

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 23:15:36