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

基于jQuery的表格CRUD与本地存储添加行失效问题排查

解决jQuery CRUD表格「Add New」按钮仅能首次添加的问题

问题原因

  1. 静态DOM元素重复使用:原代码中myEmptyRow的输入框和按钮是提前创建好的jQuery对象,第一次添加到DOM后,这些元素已属于页面节点,无法被重复插入到新行,导致后续点击添加时无元素可渲染。
  2. 函数参数传递错误:addRow函数定义为(target, data, empty),但按钮点击时传入了4个参数,导致empty被错误赋值为myButtons对象,触发不必要的tbody清空逻辑。
  3. 行数据长度判断偏差:addRow中if (data.length ==4)的判断对应已保存的4列数据(不含操作列),但新添加的空行是5列数据(含操作列),该判断不会执行,但空行本身已包含操作按钮,无需额外处理。

修复步骤

  • 将myEmptyRow从静态数组改为函数,每次调用时动态生成新的输入框和按钮元素,确保每次添加的新行都是全新的DOM节点。
  • 修正btnAdd点击事件中addRow的调用参数,去掉多余的myButtons,正确传递empty布尔值。

修改后的完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <title>CRUD Table jQuery</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>

<body>
    <div class="container">
        <div class="row">
            <div class="col-md-12 text-right">
                <input type="button" id="btnAdd" class="btn btn-primary para" value="Add New" />
            </div>
        </div>

        <div class="row pt-3">
          <div class="col-md-12 col-sm-12 col-12 p-2 ">
            <table id="tblData" class="table table-bordered table-hover table-striped">
              <thead>
                <tr id="headings">
                  <th class="schedule-color heading">ID</th>
                  <th class="schedule-color heading">Name</th>
                  <th class="schedule-color heading">Address</th>
                  <th class="schedule-color heading">Age</th>
                  <th class="tdaction">Action</th>
                </tr>
              </thead>
              <tbody class="searchable">
              </tbody>
            </table>
          </div>
        </div>
    </div>

    <script>
        $(function() {
            // 改为函数,每次调用生成新的空行元素
            function getMyEmptyRow() {
                return [{
                    class: "tdID", content: $("<input>", { type: "text", class: "form-control txtID" })
                }, {
                class: "tdName", content: $("<input>", { type: "text", class: "form-control txtName"})
                }, {
                class: "tdAddress", content: $("<input>", { type: "text", class: "form-control txtAddress"})
                }, {
                class: "tdAge", content: $("<input>", { type: "text", class: "form-control txtAge" })
                }, {
                class: "tdAction",
                content: [
                $("<button>", {
                    class: "btn btn-sm btn-success btn-save"
                }).html("Save"),
                $("<button>", {
                    class: "btn btn-sm btn-success btn-cancel"
                }).html("Delete")
                ]
                }];
            }

            var myButtons = {
                edit: [
                $("<button>", {
                    class: "btn btn-success btn-sm btn-edit"
                }).html("Edit"),
                $("<button>", {
                    class: "btn btn-danger btn-sm"
                }).html("Delete")
                ],
                update: [
                $("<button>", {
                    class: "btn btn-success btn-sm btn-save"
                }).html("Update"),
                $("<button>", {
                    class: "btn btn-danger btn-sm"
                }).html("Delete")
                ]
            };

            function getStore(index) {
                console.log("Get data for " + index);
                return JSON.parse(localStorage.getItem(index));
            }

            function saveStore(index, data) {
                console.log("Saving Data to " + index, data);
                localStorage.setItem(index, JSON.stringify(data));
            }

            function deleteStore(index) {
                console.log("Deleting Data for " + index);
                localStorage.removeItem(index);
            }

            function addRow(target, data, empty) {
                if (target == undefined) {
                target = $("table:eq(0)");
                }
                if (empty == undefined) {
                empty = false;
                }
                if (data == null) {
                return false;
                }
                console.log("Add Row to " + target.attr("id"), empty);
                if (empty) {
                $("tbody", target).html("");
                }
                var row = $("<tr>").appendTo($("tbody", target));
                if (data == undefined) {
                $("<td>", {
                    colspan: 4,
                    class: "text-center"
                }).appendTo(row);
                } else {
                row.addClass("trNewRow");
                $.each(data, function(i, cell) {
                    $("<td>", {
                    class: cell.class
                    }).append(cell.content).appendTo(row);
                });
                }

                if (data.length == 4) {
                $("<td>", {
                    class: "tdAction"
                }).append(myButtons.edit).appendTo(row);
                }
                return row;
            }

            function saveRow(row) {
                if (row == undefined) {
                    return false;
                }
                var rowData = [{
                    class: "tdID",
                    content: $(".txtID", row).val()
                    },{
                        class: "tdName",
                        content: $(".txtName", row).val()
                    }, {
                        class: "tdAddress",
                        content: $(".txtAddress", row).val()
                    }, {
                        class: "tdAge",
                        content: $(".txtAge", row).val()
                    }
                ];
                $.each(rowData, function(i, c) {
                $("." + c.class, row).html(c.content);
                });
                $(".tdAction", row).html(myButtons.edit);
                saveStore("row-" + row.index(), rowData);
            }

            function init() {
                if (localStorage.length == 0) {
                addRow($("#tblData"));
                } else {
                console.log("Found Local Storage. Rows: " + localStorage.length);
                $.each(localStorage, function(k, o) {
                    var rowData = getStore(k);
                    console.log(k, rowData);
                    addRow($("#tblData"), rowData);
                });
                }
            }

            init();

            $("#btnAdd").click(function() {
                // 调用函数获取新的空行数据,修正参数传递
                addRow($("#tblData"), getMyEmptyRow(), $("#tblData tbody tr td").length == 1 ? true : false);
            });

            $('#tblData').on('click', '.btn-save', function() {
                saveRow($(this).closest("tr"));
            });

            $('#tblData').on('click', '.btn-danger, .btn-cancel', function() {
                deleteStore("row-" + $(this).closest("tr").index());
                $(this).closest("tr").remove();
                if ($("#tblData tbody tr").length == 0) {
                addRow($("#tblData "));
                }
            });

            $('#tblData').on('click', '.btn-edit', function() {
                var row = $(this).closest("tr");
                $(".tdID", row).html("<input type='text' value='" + $(".tdID", row).html() + "' class='form-control txtID' />");
                $(".tdName", row).html("<input type='text' value='" + $(".tdName", row).html() + "' class='form-control txtName' />");
                $(".tdAddress", row).html("<input type='text' value='" + $(".tdAddress", row).html() + "' class='form-control txtAddress' />");
                $(".tdAge", row).html("<input type='text' value='" + $(".tdAge", row).html() + "' class='form-control txtAge' />");
                $(".tdAction", row).html(myButtons.update);
            });
                    
        });

    </script> 
</body> 
</html>

内容的提问来源于stack exchange,提问作者Nirantharika Selvachandran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 20:57:16