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

React项目中Bootstrap可编辑动态成绩表格开发求助

解决React+Bootstrap成绩表格的动态数据与编辑问题

问题分析

原代码存在几个核心问题:

  • 数据结构不合理:用字符串数组存储学生信息,无法承载学号、姓名、各科成绩等多字段数据
  • 表格布局不规范:用div手动模拟表格列,容易出现对齐错乱,Bootstrap自带的table组件更适合这类结构化表格场景
  • 编辑逻辑单一:仅支持单个字段编辑,无法满足姓名、学号等多字段编辑需求

修正方案

下面是重构后的代码,解决了上述问题,同时实现动态数据渲染、多字段编辑需求,并保证表格布局的一致性:

import React, { useState } from 'react';

function ExamMarksTable() {
    // 重构数据结构:每个学生对象包含所有所需字段
    const [students, setStudents] = useState([
        {
            id: 1,
            rollNo: "CS001",
            prnNo: "2023CS001",
            name: "张三",
            ese: 62,
            midSem: 27,
            prOr: 22,
            termWork: 23,
            total: 134
        },
        {
            id: 2,
            rollNo: "CS002",
            prnNo: "2023CS002",
            name: "李四",
            ese: 58,
            midSem: 25,
            prOr: 20,
            termWork: 21,
            total: 124
        }
    ]);

    // 记录当前编辑的学生ID和临时编辑数据
    const [editingId, setEditingId] = useState(null);
    const [tempStudent, setTempStudent] = useState({});

    // 开启编辑模式,复制当前学生数据到临时对象
    const handleEdit = (student) => {
        setEditingId(student.id);
        setTempStudent({ ...student });
    };

    // 保存编辑内容,更新学生列表并退出编辑模式
    const handleSave = () => {
        setStudents(students.map(s => s.id === editingId ? tempStudent : s));
        setEditingId(null);
    };

    // 取消编辑,直接退出编辑模式
    const handleCancel = () => {
        setEditingId(null);
    };

    // 处理临时编辑数据的字段更新
    const handleInputChange = (field, value) => {
        setTempStudent(prev => ({ ...prev, [field]: value }));
    };

    return (
        <div className="container-fluid mt-4">
            <div className="card">
                <div className="card-header bg-dark text-white fs-4 fw-bold">
                    CO Attainment from University Exam
                </div>
                <div className="card-body p-0">
                    <table className="table table-bordered table-hover align-middle">
                        <thead className="table-light">
                            <tr>
                                <th className="text-center" style={{ width: "5%" }}>Sr.No</th>
                                <th className="text-center" style={{ width: "10%" }}>Roll No.</th>
                                <th className="text-center" style={{ width: "15%" }}>Prn No.</th>
                                <th className="text-center" style={{ width: "20%" }}>Student Name</th>
                                {/* 合并表头:各科成绩区域 */}
                                <th colSpan="5" className="text-center">
                                    Exam Scores (Total: 150)
                                </th>
                                <th className="text-center" style={{ width: "10%" }}>操作</th>
                            </tr>
                            <tr>
                                <th></th>
                                <th></th>
                                <th></th>
                                <th></th>
                                <th className="text-center">ESE (70)</th>
                                <th className="text-center">Mid Sem (30)</th>
                                <th className="text-center">PR/OR (25)</th>
                                <th className="text-center">Term Work (25)</th>
                                <th className="text-center">Total</th>
                                <th></th>
                            </tr>
                        </thead>
                        <tbody>
                            {students.map((student, index) => (
                                <tr key={student.id}>
                                    <td className="text-center">{index + 1}</td>
                                    {/* 学号编辑逻辑 */}
                                    <td>
                                        {editingId === student.id ? (
                                            <input
                                                type="text"
                                                className="form-control"
                                                value={tempStudent.rollNo}
                                                onChange={(e) => handleInputChange('rollNo', e.target.value)}
                                            />
                                        ) : (
                                            student.rollNo
                                        )}
                                    </td>
                                    {/* PRN号编辑逻辑 */}
                                    <td>
                                        {editingId === student.id ? (
                                            <input
                                                type="text"
                                                className="form-control"
                                                value={tempStudent.prnNo}
                                                onChange={(e) => handleInputChange('prnNo', e.target.value)}
                                            />
                                        ) : (
                                            student.prnNo
                                        )}
                                    </td>
                                    {/* 姓名编辑逻辑 */}
                                    <td>
                                        {editingId === student.id ? (
                                            <input
                                                type="text"
                                                className="form-control"
                                                value={tempStudent.name}
                                                onChange={(e) => handleInputChange('name', e.target.value)}
                                            />
                                        ) : (
                                            student.name
                                        )}
                                    </td>
                                    {/* 成绩字段(如需编辑可参考上面的输入框逻辑) */}
                                    <td className="text-center">{student.ese}</td>
                                    <td className="text-center">{student.midSem}</td>
                                    <td className="text-center">{student.prOr}</td>
                                    <td className="text-center">{student.termWork}</td>
                                    <td className="text-center fw-bold">{student.total}</td>
                                    {/* 操作按钮组 */}
                                    <td className="text-center">
                                        {editingId === student.id ? (
                                            <div className="d-flex gap-2 justify-content-center">
                                                <button className="btn btn-sm btn-success" onClick={handleSave}>
                                                    保存
                                                </button>
                                                <button className="btn btn-sm btn-secondary" onClick={handleCancel}>
                                                    取消
                                                </button>
                                            </div>
                                        ) : (
                                            <button className="btn btn-sm btn-primary" onClick={() => handleEdit(student)}>
                                                编辑
                                            </button>
                                        )}
                                    </td>
                                </tr>
                            ))}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    );
}

export default ExamMarksTable;

关键改进点

  • 数据结构优化:改用对象数组存储每个学生的完整信息,方便管理多字段数据,也便于后续从接口获取数据直接替换
  • Bootstrap Table组件:使用原生table搭配Bootstrap的table类,自动处理列对齐和响应式布局,避免手动div布局的错乱问题
  • 多字段编辑支持:通过editingId标记当前编辑的学生,临时存储编辑内容,保存时批量更新学生数据
  • 表头合并:使用colSpan实现成绩区域的表头合并,完全匹配需求中的表格结构
  • 操作逻辑简化:合并编辑、保存、取消逻辑,代码结构更清晰,易维护和扩展

内容的提问来源于stack exchange,提问作者Vardhaman Begani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 10:32:06