
本教程详细阐述了如何利用javascript的事件委托机制,实现表格中单行商品总价和整体订单总价的实时计算与更新。通过监听表格的`input`事件,我们能够即时响应用户对单价和数量的修改,自动更新相关字段,显著提升用户体验,并提供了负值输入的校验与处理方法。
在现代Web应用中,实时反馈是提升用户体验的关键。对于包含可编辑数值的表格,例如订单系统中的商品单价和数量,用户期望在输入数据后立即看到总价的更新,而不是点击一个额外的“计算”按钮。本教程将指导您如何使用JavaScript实现这一功能,通过事件委托机制优化性能,并确保数据的有效性。
原始的实现方式依赖于一个显式的“Calculate Grand Total Price”按钮来触发所有计算。这种模式导致用户在每次修改单价或数量后,都需要手动点击按钮才能看到更新,降低了交互效率。
我们的目标是:
为了实现这一目标,我们将采用事件委托(Event Delegation)技术,在表格的父元素上监听input事件,而不是为每个输入框单独添加事件监听器。
立即学习“Java免费学习笔记(深入)”;
首先,我们来看一下表格的HTML结构。这是一个典型的订单表格,包含多行商品信息,每行有单价、数量和总价的输入框。
<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>
<td><input type="text" value=""></td>
<td><input type="text" value=""></td>
<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, Quantity, Total 是我们关注的输入框 -->
<td class="price"><input type="number" value="0.00"></td>
<td class="quantity"><input type="number" value="0"></td>
<td class="total"><input type="number" value="0.00" disabled></td>
</tr>
<!-- 更多行... -->
</tbody>
<tfoot>
<tr>
<td class="background-colour" colspan="5">
<!-- 原始的计算按钮将从这里移除 -->
</td>
<td class="background-colour" colspan="2">
<!-- 总订单价显示在这里 -->
<input type="number" name="Grand Total Price" value="0.00" class="GrandTotal" disabled>
</td>
</tr>
</tfoot>
</table>关键点:
我们将修改JavaScript代码,实现事件委托和实时计算逻辑。
// 确保DOM完全加载后再执行脚本
window.addEventListener("DOMContentLoaded", () => {
// 对整个表格 #myTable 绑定 'input' 事件监听器
// 'input' 事件会在 <input>, <select>, <textarea> 的值改变时触发
document.getElementById("myTable").addEventListener("input", () => {
let rows = document.querySelectorAll("tbody tr"); // 获取所有数据行
let negativeValuesDetected = false; // 标记是否检测到负值
// 使用Array.from或展开运算符将NodeList转换为数组,以便使用map和reduce
let grandTotal = Array.from(rows).map(row => {
// 获取当前行中的单价、数量和总计输入框
let quantityInput = row.querySelector(".quantity input");
let priceInput = row.querySelector(".price input");
let totalInput = row.querySelector(".total input");
// 解析输入值,确保它们是数字
let quantity = parseInt(quantityInput.value) || 0; // 如果解析失败,默认为0
let price = parseFloat(priceInput.value) || 0.00; // 如果解析失败,默认为0.00
// 负值输入校验与处理
if (quantity < 0 || price < 0) {
negativeValuesDetected = true; // 标记存在负值
quantity = 0; // 将数量重置为0
price = 0.00; // 将价格重置为0.00
quantityInput.value = "0"; // 更新输入框显示
priceInput.value = "0.00"; // 更新输入框显示
}
// 计算当前行的总价
let total = quantity * price;
totalInput.value = total.toFixed(2); // 更新当前行的总计输入框,保留两位小数
return total; // 返回当前行的总价,供后续累加
}).reduce((accumulator, currentValue) => accumulator + currentValue, 0); // 累加所有行的总价得到Grand Total
// 更新总订单价显示
document.querySelector(".GrandTotal").value = grandTotal.toFixed(2);
// 如果检测到负值,则弹出警告
if (negativeValuesDetected) {
alert("不允许输入负值!已自动重置为零。");
}
});
});代码解析:
CSS代码主要负责表格的布局和样式,它不直接影响计算逻辑,但对于用户界面的美观性和可读性至关重要。原始的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 类已不再需要,因为我们移除了按钮 */
.GrandTotal {
background-color: silver;
font-size: 18pt;
float:right;
}
tr:hover {
background-color: yellow;
}
.background-colour {
background-color: skyblue;
}
body {
background-color: lemonchiffon;
}由于总计是实时更新的,原有的“Calculate Grand Total Price”按钮就不再需要了。我们需要从tfoot部分移除这个按钮。
<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>
<!-- ... (保持与原HTML相同的<tbody>内容) ... -->
<tr>
<td class="No">1</td>
<td><input type="text" value=""></td>
<td><input type="text" value=""></td>
<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>
<td class="price"><input type="number" value="0.00"></td>
<td class="quantity"><input type="number" value="0"></td>
<td class="total"><input type="number" value="0.00" disabled></td>
</tr>
<!-- 更多行... -->
<tr>
<td class="No">5</td>
<td><input type="text" value=""></td>
<td><input type="text" value=""></td>
<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>
<td class="price"><input type="number" value="0.00"></td>
<td class="quantity"><input type="number" value="0"></td>
<td class="total"><input type="number" value="0.00" disabled></td>
</tr>
</tbody>
<tfoot>
<tr>
<td class="background-colour" colspan="5">
<!-- 移除原始的计算按钮 -->
</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>通过采用事件委托机制,我们成功地将表格的行总价和总订单价的计算逻辑从一个手动触发的按钮操作,转变为实时的、响应式的用户交互。这种方法不仅简化了HTML结构,提高了代码的可维护性,更重要的是,极大地提升了用户体验,使数据输入和反馈变得即时而流畅。
以上就是JavaScript表格数据实时计算与更新:事件委托实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号