图书订购系统:输入Unit Price和Quantity时如何实时更新Total?
图书订购系统实时计算实现方案
需求说明
开发图书订购系统时,需要实现两个核心功能:
- 输入单价和数量后,无需点击按钮,立即更新对应行的总价
- 点击「计算总价」按钮时,汇总所有行的总价并显示在「总计」输入框中
修改后的完整代码
HTML代码(无需改动)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Book Ordering System</title> <link rel="stylesheet" href="CSS/book-order.css"> <script src="book-order.js"></script> </head> <body> <h1>Book Ordering System</h1> <table id="myTable"> <thead> <tr> <th>No.</th> <th>Book Title</th> <th>Author</th> <th>Category</th> <th>Unit Price</th> <th>Quantity</th> <th>Total</th> </tr> </thead> <tbody> <tr> <td class="No">1</td> <!--Book Title--> <td><input type="text" value=""></td> <!--Author--> <td><input type="text" value=""></td> <!--Category--> <td> <select> <option value="Please choose the category..." disabled selected>Please choose the category...</option> <option value="Business">Business</option> <option value="Fiction">Fiction</option> <option value="Mathematics">Mathematics</option> <option value="Technology">Technology</option> </select> </td> <!--Unit Price--> <td class="price"><input type="number" value="0.00"></td> <!--Quantity--> <td class="quantity"><input type="number" value="0"></td> <!--Total--> <td class="total"><input type="number" value="0.00" disabled></td> </tr> <tr> <td class="No">2</td> <!--Book Title--> <td><input type="text" value=""></td> <!--Author--> <td><input type="text" value=""></td> <!--Category--> <td> <select> <option value="Please choose the category..." disabled selected>Please choose the category...</option> <option value="Business">Business</option> <option value="Fiction">Fiction</option> <option value="Mathematics">Mathematics</option> <option value="Technology">Technology</option> </select> </td> <!--Unit Price--> <td class="price"><input type="number" value="0.00"></td> <!--Quantity--> <td class="quantity"><input type="number" value="0"></td> <!--Total--> <td class="total"><input type="number" value="0.00" disabled></td> </tr> <tr> <td class="No">3</td> <!--Book Title--> <td><input type="text" value=""></td> <!--Author--> <td><input type="text" value=""></td> <!--Category--> <td> <select> <option value="Please choose the category..." disabled selected>Please choose the category...</option> <option value="Business">Business</option> <option value="Fiction">Fiction</option> <option value="Mathematics">Mathematics</option> <option value="Technology">Technology</option> </select> </td> <!--Unit Price--> <td class="price"><input type="number" value="0.00"></td> <!--Quantity--> <td class="quantity"><input type="number" value="0"></td> <!--Total--> <td class="total"><input type="number" value="0.00" disabled></td> </tr> <tr> <td class="No">4</td> <!--Book Title--> <td><input type="text" value=""></td> <!--Author--> <td><input type="text" value=""></td> <!--Category--> <td> <select> <option value="Please choose the category..." disabled selected>Please choose the category...</option> <option value="Business">Business</option> <option value="Fiction">Fiction</option> <option value="Mathematics">Mathematics</option> <option value="Technology">Technology</option> </select> </td> <!--Unit Price--> <td class="price"><input type="number" value="0.00"></td> <!--Quantity--> <td class="quantity"><input type="number" value="0"></td> <!--Total--> <td class="total"><input type="number" value="0.00" disabled></td> </tr> <tr> <td class="No">5</td> <!--Book Title--> <td><input type="text" value=""></td> <!--Author--> <td><input type="text" value=""></td> <!--Category--> <td> <select> <option value="Please choose the category..." disabled selected>Please choose the category...</option> <option value="Business">Business</option> <option value="Fiction">Fiction</option> <option value="Mathematics">Mathematics</option> <option value="Technology">Technology</option> </select> </td> <!--Unit Price--> <td class="price"><input type="number" value="0.00"></td> <!--Quantity--> <td class="quantity"><input type="number" value="0"></td> <!--Total--> <td class="total"><input type="number" value="0.00" disabled></td> </tr> </tbody> <tfoot> <tr> <td class="background-colour" colspan="5"> <button type="button" onclick="calculateTotal()" class="Button">Calculate Grand Total Price</button> </td> <td class="background-colour" colspan="2"> <input type="number" name="Grand Total Price" value="0.00" class="GrandTotal" disabled> </td> </tr> </tfoot> </table> </body> </html>
CSS代码(无需改动)
table,td { padding: 0.5rem; border: 3px solid; border-collapse:collapse; } h1 { font-family: 'Ubuntu', cursive; } th { background-color: skyblue; font-weight: bold; padding: 0.5rem; border: 3px solid; border-collapse:collapse; } tbody { background-color: white; } .No { text-align: right; } td:nth-child(7) input[type="number"]{ text-align: right; background-color: silver; } td:nth-child(6) input[type="number"]{ text-align: right; } td:nth-child(5) input[type="number"]{ text-align: right; } tfoot tr td:last-child input[type="number"]{ text-align: right; } input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } tfoot { font-weight: bold; } .Button { float:right; } .GrandTotal { background-color: silver; font-size: 18pt; float:right; } tr:hover { background-color: yellow; } .background-colour { background-color: skyblue; } body { background-color: lemonchiffon; }
JavaScript代码(核心修改)
// 单行总价计算逻辑,同时支持实时更新和汇总计算 function calculateRowTotal(row) { let quantityInput = row.querySelector(".quantity input"); let priceInput = row.querySelector(".price input"); let totalInput = row.querySelector(".total input"); // 处理空输入,避免NaN错误 let quantity = parseInt(quantityInput.value) || 0; let price = parseFloat(priceInput.value) || 0; let isNegative = false; // 负数校验与重置 if (quantity < 0 || price < 0) { isNegative = true; quantity = 0; price = 0; quantityInput.value = "0"; priceInput.value = "0.00"; } let total = quantity * price; totalInput.value = total.toFixed(2); return { total, isNegative }; } // 页面加载完成后,绑定实时输入监听 document.addEventListener('DOMContentLoaded', function() { // 获取所有单价和数量输入框 const priceInputs = document.querySelectorAll('.price input'); const quantityInputs = document.querySelectorAll('.quantity input'); // 单价输入变化时,更新对应行总价 priceInputs.forEach(input => { input.addEventListener('input', function() { calculateRowTotal(this.closest('tr')); }); }); // 数量输入变化时,更新对应行总价 quantityInputs.forEach(input => { input.addEventListener('input', function() { calculateRowTotal(this.closest('tr')); }); }); }); // 汇总所有行总价,计算总计 function calculateTotal() { let rows = document.querySelectorAll("tbody tr"); let grandTotal = 0; let hasNegativeInput = false; rows.forEach(row => { const { total, isNegative } = calculateRowTotal(row); grandTotal += total; if (isNegative) hasNegativeInput = true; }); document.querySelector(".GrandTotal").value = grandTotal.toFixed(2); if (hasNegativeInput) { alert("禁止输入负数!"); } }
关键改动说明
- 抽离复用逻辑:将单行总价计算的核心逻辑拆分为
calculateRowTotal函数,既用于实时更新,也用于汇总计算,避免代码冗余 - 实时事件监听:通过
input事件监听单价和数量输入框的内容变化,只要用户输入或修改数值,立即触发对应行的总价计算 - 输入容错处理:用
|| 0处理空输入的情况,防止出现NaN计算错误 - 保留原有校验:维持了负数输入的重置和提示逻辑,确保数据合法性
内容的提问来源于stack exchange,提问作者LLX
相关产品推荐
相关产品推荐

