如何使用JavaScript在HTML表格无刷新显示已Push的对象并兼容Filter过滤
问题分析与解决方案
你的代码存在以下几个核心问题,导致新增产品无法在表格中显示:
- 未给「Add Product」按钮绑定点击事件,点击后无任何逻辑执行
showProducts()函数会遍历整个数组渲染所有产品,直接调用会重复绘制已有数据- 模态框中的日期输入字段与产品对象的日期字段不匹配,且未做格式转换
- 新增产品时未生成唯一ID
以下是修复后的完整代码:
HTML 部分(保持原结构)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="container"> <div class="headtext"> <h1>Products</h1> <button id="showFilter" class="btn btn-outline-info" data-toggle="collapse" data-target="#filterDiv">Show Filter</button> </div> <div class="collapse" id="filterDiv"> <div class="form-group form-inline"> <label>Name:</label> <input type="text" class="form-control" id="pName" /> <label>Price between</label> <input type="number" class="form-control" id="minPrice" placeholder="0" /> <label>and</label> <input type="number" class="form-control" id="maxPrice" placeholder="10000" value="10000" /> <button id="clearButton" class="btn btn-warning">Clear</button> </div> </div> <table id="product" class="table table-striped"> <tr> <th>Product Name</th> <th>Product Number</th> <th>Color</th> <th>List Price</th> <th>Modified Date</th> <th>Actions</th> </tr> </table> <!-- Button trigger modal --> <button type="button" class="btn btn-primary" style="margin-bottom: 20px;" data-toggle="modal" data-target="#addModal"> Create New Product </button> <!-- Modal --> <div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Add Product</h5> </div> <div class="modal-body"> <form action=""> <div class="form-group"> <label for="productName">Name</label> <input id="productName" type="text" class="form-control" placeholder="Enter Product Name" required> </div> <div class="form-group"> <label for="productNumber">Product Number</label> <input id="productNumber" type="text" class="form-control" placeholder="Enter Product Number" required> </div> <div class="form-group"> <label for="productColor">Color</label> <input id="productColor" type="text" class="form-control" placeholder="Enter Product color"> </div> <div class="form-group"> <label for="listPrice">List Price</label> <input id="listPrice" type="number" class="form-control" placeholder="Enter Price" min="0" max="10000"> </div> <div class="form-group"> <label for="startDate">Sell Start Date</label> <input id="startDate" type="datetime-local" class="form-control" placeholder="Enter Product color"> </div> <button class="btn btn-success" id="btnSubmit">Add Product</button> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-danger" data-dismiss="modal">Close</button> </div> </div> </div> </div> </div>
JavaScript 部分(修复后代码)
var products = [{ ID: 1, productName: "HL Road Frame - Back, 58", productNumber: "FR-R92B-58", color: "Black", listPrice: 900.00, modifiedDate: "11 November 2021" }, { ID: 2, productName: "HL Mountain Frame - Silver, 41", productNumber: "FR-M945-42", color: "Silver", listPrice: 1364.50, modifiedDate: "16 August 2022" }, { ID: 3, productName: "HL Road Frame - Back, 58", productNumber: "FR-R92B-58", color: "Black", listPrice: 700.00, modifiedDate: "11 November 2021" }, { ID: 4, productName: "HL Road Frame - Back, 58", productNumber: "FR-R92B-58", color: "Black", listPrice: 600.00, modifiedDate: "11 November 2021" }, ]; // 调整渲染函数,支持单个产品或全部产品渲染 function showProducts(productToRender) { const itemsToRender = productToRender ? [productToRender] : products; for (let product of itemsToRender) { // 跳过已渲染的产品,避免重复绘制 if (product.tableRow) continue; let tableRow = $("<tr></tr>").addClass("productData"); tableRow.append($("<td></td>").text(product.productName)); tableRow.append($("<td></td>").text(product.productNumber)); tableRow.append($("<td></td>").text(product.color)); tableRow.append($("<td></td>").text(product.listPrice)); tableRow.append($("<td></td>").text(product.modifiedDate)); product.tableRow = tableRow; $("#product").append(tableRow); } } showProducts(); // 新增产品事件绑定 $("#btnSubmit").on("click", function(e) { e.preventDefault(); // 获取表单输入值 const productName = $("#productName").val().trim(); const productNumber = $("#productNumber").val().trim(); const color = $("#productColor").val().trim() || ""; const listPrice = parseFloat($("#listPrice").val()) || 0; const startDate = $("#startDate").val(); // 转换日期格式为"DD Month YYYY" let modifiedDate = ""; if (startDate) { const dateObj = new Date(startDate); modifiedDate = dateObj.toLocaleDateString('en-US', { day: 'numeric', month: 'long', year: 'numeric' }); } // 生成唯一ID const maxId = products.length ? Math.max(...products.map(p => p.ID)) : 0; const newProduct = { ID: maxId + 1, productName, productNumber, color, listPrice, modifiedDate }; // 添加到数组并渲染 products.push(newProduct); showProducts(newProduct); // 关闭模态框并重置表单 $("#addModal").modal("hide"); $("#addModal form")[0].reset(); }); /* 产品过滤功能 */ function filterProduct() { let pName = $("#pName").val().toLowerCase(); // 处理空值,默认最小价格0,最大价格10000 let minPrice = $("#minPrice").val() ? parseFloat($("#minPrice").val()) : 0; let maxPrice = $("#maxPrice").val() ? parseFloat($("#maxPrice").val()) : 10000; for (let product of products) { let toDisplay = (pName.trim() === "" || product.productName.toLowerCase().includes(pName)) && product.listPrice >= minPrice && product.listPrice <= maxPrice; const tableRow = product.tableRow; toDisplay ? (tableRow.removeClass("fadeOut").fadeIn()) : (tableRow.addClass("fadeOut").fadeOut()); } } $("#filterDiv input").on("change", filterProduct); // 清除过滤器按钮事件 $("#clearButton").on("click", function() { $("#pName").val(""); $("#minPrice").val(""); $("#maxPrice").val("10000"); filterProduct(); }); /* 过滤器显示/隐藏切换 */ $("#showFilter").click(function() { $(this).text($(this).text() === 'Show Filter' ? 'Hide Filter' : 'Show Filter'); });
关键修复说明
- 重构
showProducts()函数,支持单个产品渲染,避免重复绘制已有数据 - 新增产品按钮绑定点击事件,处理表单数据、生成唯一ID、转换日期格式,完成后渲染新产品
- 修复过滤器价格空值处理逻辑,避免空字符串与数字比较导致的错误
- 添加清除过滤器按钮的事件处理,实现一键重置过滤条件
内容的提问来源于stack exchange,提问作者luka
相关产品推荐
相关产品推荐

