新闻中心

J*aScript实现HTML表格数据的实时计算与更新

2025-11-10
浏览次数:
返回列表

JavaScript实现HTML表格数据的实时计算与更新

本文详细介绍了如何利用j*ascript事件委托机制,实现html表格中单行总价和总计的实时动态更新。通过监听父级表格的input事件,我们能够即时捕获用户在单价和数量输入框中的改动,并同步更新相应行的总价及整个订单的总价,同时包含对负数输入的处理,显著提升了用户体验。

在构建交互式网页应用时,尤其是涉及数据录入和计算的场景,如订单系统或购物车,实时反馈是提升用户体验的关键。传统的做法是让用户在输入数据后点击一个按钮来触发计算,但这往往导致操作流程繁琐且效率低下。本教程将深入探讨如何通过J*aScript事件委托技术,实现HTML表格中单行总价(Total)和总计(Grand Total)的即时动态更新,从而避免手动触发计算的需要。

传统计算方式的局限性

在许多初始实现中,计算逻辑通常封装在一个函数中,并通过按钮的onclick事件来调用。例如,以下J*aScript代码展示了一个典型的计算逻辑:

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(isNaN(quantity) || quantity < 0){ // 增加对NaN的检查
      negative = true;
      quantity = 0;
      quantityInput.value = "0";
    }
    if(isNaN(price) || price < 0){ // 增加对NaN的检查
      negative = true;
      price = 0.00;
      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("不允许输入负值!已自动重置为0。")
  }
}

这种方法要求用户每次更改单价或数量后,都必须点击“Calculate Grand Total Price”按钮才能看到更新后的结果。这显然不是一个理想的用户体验。

实时动态更新的实现:事件委托

为了实现实时更新,我们需要在用户输入时即刻触发计算。最有效的方法是利用事件委托(Event Delegation),将事件监听器附加到父级元素上,而不是每个单独的输入框。当事件在子元素上触发时,它会冒泡到父元素,父元素上的监听器就能捕获并处理它。

1. HTML结构准备

首先,确保你的HTML表格结构清晰,并且包含用于单价、数量、单行总价和总计的输入字段,并赋予相应的类名以便J*aScript选择器定位。

<!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">
</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>
                <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">2</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>

    <script src="book-order.js"></script> <!-- 确保在</body>标签前引入JS -->
</body>
</html>

请注意,我们移除了tfoot中原有的“Calculate Grand Total Price”按钮,因为我们的目标是实现自动实时更新。

2. J*aScript事件委托逻辑

我们将使用DOMContentLoaded事件来确保DOM完全加载后再绑定事件监听器,避免因元素未加载而导致的错误。然后,在整个myTable上监听input事件。当任何input元素的值发生变化时,这个事件都会触发。

// book-order.js
window.addEventListener("DOMContentLoaded", () => {
  // 当页面DOM内容加载完毕后执行
  const myTable = document.getElementById("myTable");

  // 绑定input事件到整个表格,利用事件委托
  myTable.addEventListener("input", (event) => {
    // 检查触发事件的元素是否是我们关心的单价或数量输入框
    const target = event.target;
    if (!target.matches('.quantity input') && !target.matches('.price input')) {
        // 如果不是单价或数量输入框,则不执行计算
        return;
    }

    let rows = document.querySelectorAll("tbody tr");
    let negativeValueDetected = false; // 用于标记是否检测到负值

    // 使用Array.prototype.map和Array.prototype.reduce进行更简洁的计算
    let grandTotal = [...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);
      let price = parseFloat(priceInput.value);

      // 输入验证:处理非数字或负数输入
      if (isNaN(quantity) || quantity < 0) {
        negativeValueDetected = true;
        quantity = 0;
        quantityInput.value = "0"; // 重置为0
      }
      if (isNaN(price) || price < 0) {
        negativeValueDetected = true;
        price = 0.00;
        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 (negativeValueDetected) {
      alert("不允许输入负值!已自动重置为0。");
    }
  });
});

3. CSS样式(可选)

CSS部分保持不变,它主要负责表格的视觉呈现。

网趣网上购物系统旗舰版 网趣网上购物系统旗舰版

网趣网上购物系统支持PC电脑版+手机版+APP,数据一站式更新,支持微信支付与支付宝支付接口,是专业的网上商城系统,网趣商城系统支持淘宝数据包导入,实现与淘宝同步更新!支持上传图片水印设置、图片批量上传功能,同时支持订单二次编辑以及多级分类隐藏等实用功能,新版增加商品大图浏览与列表显示功能,使分类浏览更方便,支持最新的支付宝即时到帐接口。

网趣网上购物系统旗舰版 0 查看详情 网趣网上购物系统旗舰版
/* book-order.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 { /* 此处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;
}

关键改进点和注意事项

  1. 事件委托 (myTable.addEventListener("input", ...)):

    • 将事件监听器绑定到父元素myTable上,而不是每个quantity或price输入框。这减少了事件监听器的数量,提高了性能,尤其是在表格行数很多时。
    • input事件在input元素的值发生变化时立即触发,提供了实时反馈。
    • 通过event.target检查事件源,确保只有单价和数量输入框的变化才会触发计算,避免不必要的计算。
  2. DOMContentLoaded:

    • window.addEventListener("DOMContentLoaded", ...)确保J*aScript代码在DOM完全加载和解析后才执行。这保证了myTable元素及其内部的输入框在尝试绑定事件和查询时是可用的。
  3. 数据类型转换和验证:

    • parseInt()和parseFloat()用于将输入值转换为数字。
    • 增加了对isNaN()的检查,以处理用户可能输入非数字字符的情况。
    • 对负数输入进行了处理:将其重置为0并弹出警告,这增强了数据的健壮性。
  4. 数组方法优化:

    • 使用[...rows].map(...)将NodeList转换为数组,然后对每行执行计算并返回其总价。
    • 使用.reduce(...)方法简洁地累加所有行的总价,生成最终的grandTotal。这种函数式编程风格使代码更具可读性和维护性。
  5. 数值格式化:

    • toFixed(2)用于将计算结果格式化为两位小数,确保货币显示的一致性。

总结

通过采用事件委托和优化J*aScript逻辑,我们成功地将一个需要手动触发的表格计算系统改造为实时动态更新的交互式应用。这种方法不仅提升了用户体验,也展示了现代J*aScript在DOM操作和数据处理方面的强大能力和简洁性。在开发涉及大量用户输入和计算的Web界面时,实时反馈和高效的事件处理是不可或缺的考量。

以上就是J*aScript实现HTML表格数据的实时计算与更新的详细内容,更多请关注其它相关文章!


# javascript  # 转换为  # 淘宝  # 选择器  # 自定义  # 加载  # 网上  # 绑定  # 购物系统  # 弹出  # 输入框  # win  # css  # java  # html  # js  # node  # go  # app  # edge  # ubuntu  # css样  # 网站建设的内容怎么写  # 济南网站建设中介公司  # 浙江建设网站流程  # 抖音seo运营方式  # 东兴响应式网站建设  # 豪宅营销推广主题  # 什邡优化网站排名  # 大余seo网络营销  # 营口网站建设知识分享  # seo价格怎么查询 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: b站如何看历史记录_b站观看历史找回方法  电脑屏幕颜色不舒服怎么办_Windows夜间模式与色彩校准教程【护眼技巧】  HTML元素状态管理:根据DIV内容动态启用/禁用按钮  Composer如何在生产环境安全地执行composer update  不同用户不同价格! 索尼开启账户个性化定价测试  Golang如何实现微服务鉴权与权限控制_Golang微服务鉴权与权限管理实践  AI泡沫首次被“刺破”:GPU十年都无法存活!  html两个JS只运行一个怎么办_让双JS在html中都运行方法【技巧】  如何仅使用CSS更改登录界面背景图像图标的颜色  J*aScript类型检查_j*ascript代码规范  C++如何实现一个智能指针_手动实现C++ shared_ptr的引用计数功能  Lar*el递归关系中排除子孙节点的策略  html怎么在cmd下运行php文件_cmd运行html中php文件方法【教程】  学习通网页版快速入口 学习通官网网页版直接打开  b站怎么看视频的弹幕数量_b站弹幕数量查看方法  如何高效处理PHP中的Excel数据导入导出?PortPHP/Spreadsheet助你轻松搞定!  c++ 命名空间怎么用 c++ namespace使用指南  解决macOS Tkinter应用双击启动崩溃:PyInstaller打包指南  俄罗斯Yandex免登录入口_Yandex搜索引擎官网一键直达  谷歌学术网站直达地址 谷歌学术搜索网页版一键进入  JUnit5/Mockito:优雅测试内部依赖与异常处理的实践  抖音未来赚钱的新趋势 2025年值得关注的变现风口分析  Mac怎么查看崩溃日志_Mac控制台错误报告分析  win11 arm版怎么安装 M1/M2 Mac虚拟机安装ARM win11的方法  Go调试环境为何无法启动_Go调试器启动失败原因与解决策略  解决J*aScript中重复选择项的确认对话框显示问题  苹果手机如何防止被恶意App追踪  Python中如何避免重复条件判断:利用数据结构实现动态逻辑  Node.js 中使用 node-cron 实现定时 API 数据抓取与处理  支付宝如何设置安全保护_支付宝安全设置的全面教程  微博网页版主页入口 微博官方网站免登录访问  KFC游戏互动怎么赢取优惠券_KFC线上游戏活动参与与优惠代码赢取教程  漫蛙manwa官网登录界面_漫蛙漫画网页版主站入口  在J*a中如何使用Stream.map转换元素_Stream映射操作解析  ArchiveofOurOwn小说阅读-ArchiveofOurOwn同人作品访问链接  铁路12306卧铺选择攻略 铁路12306下铺座位预定技巧  Python getattr() 异常处理深度解析:避免程序意外退出  解决Flask中Quill编辑器内容提交失败及TypeError的指南  Odoo 16:在表单视图中基于当前记录动态修改Tree视图属性  快手网页版在线登录 快手网页版官网入口快速访问  小猿搜题在线学习页面在哪_小猿搜题在线学习中心入口  2026春节假期时间安排 2026春节假日查询  Python字典中优雅地迭代剩余元素的方法  神庙逃亡小游戏在线玩 神庙逃亡小游戏入口  深入理解Go语言中的指针类型:以*string为例  斑马英语APP如何开启夜间护眼阅读_斑马英语APP夜间模式与低蓝光设置教程  在React函数组件中利用原生HTML5进行邮箱地址验证  如何将一个大型PHP应用拆分为多个Composer包_微服务与模块化架构的Composer实践  Golang如何使用const iota_Go iota常量计数器讲解  yandex入口引擎手机版 yandex安卓版下载入口 

搜索