
本教程旨在指导开发者如何通过javascript实现html表格中单价和数量输入框的实时总计更新,并自动计算并显示总订单价格。文章将详细介绍事件委托机制的应用,以及如何优化计算逻辑,确保用户在不点击任何按钮的情况下,即可看到数据变化的即时反馈,同时包含输入验证和代码示例。
在现代Web应用中,提供即时反馈的用户体验至关重要。对于包含可编辑数据的表格,例如订单系统或购物车,用户期望在修改单价或数量后,相关行的总价以及整个订单的总价能够立即更新,而无需手动点击“计算”按钮。本教程将详细介绍如何利用JavaScript实现这一功能,通过事件委托机制优化性能,并确保代码的健壮性。
在最初的设计中,通常会有一个独立的函数(如 calculateTotal())负责遍历所有表格行,计算每行的总价,并累加得到总订单价格。这个函数通常绑定到一个按钮的 onclick 事件上。
function calculateTotal() {
let rows = document.querySelectorAll("tbody tr");
let grandTotal = 0;
let negative = false;
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
let quantityInput = row.querySelector(".quantity input");
let priceInput = row.querySelector(".price input");
let totalInput = row.querySelector(".total input");
let quantity = parseInt(quantityInput.value);
let price = parseFloat(priceInput.value); // 注意这里toFixed(2)应该在计算后
if(quantity < 0 || price < 0){
negative = true;
quantity = 0;
price = 0.00;
quantityInput.value = "0";
priceInput.value = "0.00";
}
let total = quantity * price;
totalInput.value = total.toFixed(2); // 每行总价
grandTotal += total;
}
document.querySelector(".GrandTotal").value = grandTotal.toFixed(2); // 总订单价格
if(negative){
alert("No Negative Values!")
}
}这种方式的问题在于,用户必须主动点击按钮才能看到更新,这降低了交互的流畅性。为了实现实时更新,我们需要在用户输入数据时即刻触发计算逻辑。
要实现实时更新,我们需要监听表格中单价和数量输入框的 input 事件。然而,如果表格包含大量行,为每个输入框单独添加事件监听器会增加性能开销。更优雅且高效的解决方案是使用事件委托。
立即学习“Java免费学习笔记(深入)”;
事件委托的核心思想是将事件监听器添加到父元素(例如整个表格 <table>),而不是每个子元素。当子元素上的事件被触发时,事件会冒泡到父元素,父元素上的监听器可以捕获到这个事件,并通过 event.target 属性判断是哪个子元素触发了事件,从而执行相应的逻辑。
首先,我们需要在DOM加载完成后,为整个表格元素添加一个 input 事件监听器。DOMContentLoaded 事件确保了HTML结构完全加载并解析完毕,此时可以安全地操作DOM。
window.addEventListener("DOMContentLoaded", () => {
// 当页面加载完成时
document.getElementById("myTable").addEventListener("input", () => {
// 任何输入事件都会在此处被捕获
// ... 后续计算逻辑 ...
});
});通过这种方式,无论用户在哪个单价或数量输入框中输入内容,myTable 上的 input 事件监听器都会被触发。
在 input 事件被触发后,我们需要重新计算所有行的总价,并更新总订单价格。这里可以利用现代JavaScript数组方法 map 和 reduce 来使代码更简洁和函数式。
window.addEventListener("DOMContentLoaded", () => {
document.getElementById("myTable").addEventListener("input", () => {
let rows = document.querySelectorAll("tbody tr"); // 获取所有表格行
let negative = false; // 标记是否存在负值输入
// 使用map遍历每行计算其总价,并返回一个总价数组
// 使用reduce将所有行总价累加得到grandTotal
let grandTotal = [...rows].map(row => {
let quantityInput = row.querySelector(".quantity input");
let priceInput = row.querySelector(".price input");
let totalInput = row.querySelector(".total input");
// 解析输入值,注意需要处理NaN情况,这里简化为默认0
let quantity = parseInt(quantityInput.value) || 0;
let price = parseFloat(priceInput.value) || 0.00;
// 输入验证:不允许负值
if (quantity < 0 || price < 0) {
negative = true;
quantity = 0;
price = 0.00;
quantityInput.value = "0"; // 重置为0
priceInput.value = "0.00"; // 重置为0.00
}
let total = quantity * price; // 计算当前行总价
totalInput.value = total.toFixed(2); // 更新当前行总价显示
return total; // 返回当前行总价,供后续累加
}).reduce((accumulator, currentValue) => accumulator + currentValue, 0); // 累加所有行总价
// 更新总订单价格
document.querySelector(".GrandTotal").value = grandTotal.toFixed(2);
// 如果存在负值输入,则弹出警告
if (negative) {
alert("No Negative Values!");
}
});
});由于总订单价格现在是实时更新的,原先的“Calculate Grand Total Price”按钮的 onclick 事件可以移除或修改为其他功能(例如提交订单)。在提供的优化方案中,该按钮的 onclick 属性被移除,使其不再负责计算总价。
<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>
<!-- ... 多行数据,每行包含 .price input 和 .quantity input ... -->
<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>
<!-- ... 其他行 ... -->
</tbody>
<tfoot>
<tr>
<td class="background-colour" colspan="5">
<!-- 按钮的 onclick 属性被移除,现在由实时监听器处理 -->
<!-- <button type="button" 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>CSS样式主要负责表格和输入框的视觉呈现,与JavaScript的实时计算逻辑无关,因此可以保持原样。
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;
}通过上述方法,我们成功实现了表格中单价和数量的实时更新,极大地提升了用户体验。
通过采纳这些实践,您可以构建出响应迅速、用户友好的Web表格应用。
以上就是实现交互式表格实时总计更新的JavaScript教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号