新闻中心

实现交互式表格实时总计更新的J*aScript教程

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

实现交互式表格实时总计更新的JavaScript教程

本教程旨在指导开发者如何通过j*ascript实现html表格中单价和数量输入框的实时总计更新,并自动计算并显示总订单价格。文章将详细介绍事件委托机制的应用,以及如何优化计算逻辑,确保用户在不点击任何按钮的情况下,即可看到数据变化的即时反馈,同时包含输入验证和代码示例。

在现代Web应用中,提供即时反馈的用户体验至关重要。对于包含可编辑数据的表格,例如订单系统或购物车,用户期望在修改单价或数量后,相关行的总价以及整个订单的总价能够立即更新,而无需手动点击“计算”按钮。本教程将详细介绍如何利用J*aScript实现这一功能,通过事件委托机制优化性能,并确保代码的健壮性。

传统计算方式的局限性

在最初的设计中,通常会有一个独立的函数(如 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 事件。然而,如果表格包含大量行,为每个输入框单独添加事件监听器会增加性能开销。更优雅且高效的解决方案是使用事件委托

事件委托的核心思想是将事件监听器添加到父元素(例如整个表格

),而不是每个子元素。当子元素上的事件被触发时,事件会冒泡到父元素,父元素上的监听器可以捕获到这个事件,并通过 event.target 属性判断是哪个子元素触发了事件,从而执行相应的逻辑。

步骤一:监听表格的 input 事件

首先,我们需要在DOM加载完成后,为整个表格元素添加一个 input 事件监听器。DOMContentLoaded 事件确保了HTML结构完全加载并解析完毕,此时可以安全地操作DOM。

window.addEventListener("DOMContentLoaded", () => {
  // 当页面加载完成时
  document.getElementById("myTable").addEventListener("input", () => {
    // 任何输入事件都会在此处被捕获
    // ... 后续计算逻辑 ...
  });
});

通过这种方式,无论用户在哪个单价或数量输入框中输入内容,myTable 上的 input 事件监听器都会被触发。

Ex驾校预约小程序 Ex驾校预约小程序

传统驾校预约方式步骤繁琐,效率低下,随着移动互联网科技和5G的革新,驾校考试领域迫切需要更加简洁、高效的预约方式,便捷人们的生活。因此设计基于微信小程序的驾校预约系统,改进传统驾校预约方式,实现高效的驾校学校预约。 采用腾讯提供的小程序云开发解决方案,无须服务器和域名。驾校预约管理:开始/截止时间/人数均可灵活设置,可以自定义客户预约填写的数据项驾校预约凭证:支持线下到场后校验签到/核销/二维码自

Ex驾校预约小程序2查看详情Ex驾校预约小程序

步骤二:优化计算逻辑

在 input 事件被触发后,我们需要重新计算所有行的总价,并更新总订单价格。这里可以利用现代J*aScript数组方法 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!");
    }
  });
});

HTML结构调整(可选)

由于总订单价格现在是实时更新的,原先的“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样式(保持不变)

CSS样式主要负责表格和输入框的视觉呈现,与J*aScript的实时计算逻辑无关,因此可以保持原样。

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;
}

总结与注意事项

通过上述方法,我们成功实现了表格中单价和数量的实时更新,极大地提升了用户体验。

  1. 事件委托的优势:
    • 性能优化: 只需一个事件监听器处理整个表格的输入事件,而非为每个输入框单独添加,减少了内存占用和DOM操作。
    • 动态内容支持: 如果表格行是动态添加的,新添加的行会自动继承父元素的事件监听,无需额外代码处理。
  2. 数据类型转换与验证:
    • 使用 parseInt() 和 parseFloat() 确保输入值被正确转换为数字。
    • 添加了负值验证逻辑,并在检测到负值时重置输入框并发出警告,增强了数据的完整性。
    • 为了健壮性,建议在 parseInt() 和 parseFloat() 后增加对 NaN(Not a Number)的检查,例如 parseInt(value) || 0,以防用户输入非数字字符。
  3. 浮点数精度:
    • 在进行乘法和加法运算后,使用 toFixed(2) 来格式化货币值,确保显示两位小数,避免浮点数计算的精度问题。
  4. 用户体验:
    • 实时反馈让用户操作更加直观,减少了不必要的点击和等待。

通过采纳这些实践,您可以构建出响应迅速、用户友好的Web表格应用。

以上就是实现交互式表格实时总计更新的J*aScript教程的详细内容,更多请关注其它相关文章!


# 遍历  # 宁波网站整站seo  # 天津好的网站建设单价  # 怀柔区进口网站建设风格  # seo优化有必要弄吗  # 广告营销推广推荐  # 苏州家政网站建设选择  # 荣昌机械网站建设公司  # 微信网站建设方案策划书  # seo店铺描述分类  # 四川seo排名项目  # 背景色  # 复选框  # 如何实现  # 详细介绍  # 加载  # css  # 移除  # 自定义  # 弹出  # 输入框  #   # lsp  # 内存占用  # css样式  # win  # ubuntu  # app  # go  # html  # java  # javascript 


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


相关推荐: J*a里如何使用forEach遍历Map_Map遍历方法说明  处理Kafka消费者会话超时:深入理解消息处理语义与幂等性  Python中高效且防溢出的双曲正弦计算:基于对数空间的优化策略  不同用户不同价格! 索尼开启账户个性化定价测试  如何将一个大型PHP应用拆分为多个Composer包_微服务与模块化架构的Composer实践  Golang如何优化内存分配与垃圾回收_Golang内存管理与GC优化实践  品牌机怎么重装系统 联想/戴尔/惠普笔记本恢复出厂系统教程  整合Supabase认证与Django模型:跨模式迁移的解决方案  Win11怎么开启省电模式_Win11电池节电模式自动开启  格力空气能E5故障代码是什么情况_格力空气能E5代码解析与应对措施  Lar*el 递归关系中排除指定分支的教程  百度网盘网页版入口 百度网盘网页版官方登录网址  三星ZFold5多任务卡顿_Samsung ZFold5流畅度提升  一加手机电池耗电快怎么办_一加手机电池耗电快的解决方法  解决Tabulator日期时间排序问题的专业指南  如何在低配置电脑上搭建轻量级J*a环境_占用更小的环境选择技巧  我的世界官方游戏入口 我的世界官网平台直达链接  age动漫网站入口 age动漫官网直接访问入口  打开就能玩的植物大战僵尸 植物大战僵尸网页版传送门  从J*aScript对象中精确提取指定属性的教程  ArchiveofOurOwn小说阅读-ArchiveofOurOwn同人作品访问链接  C++如何进行游戏物理模拟_使用Box2D库为C++游戏添加2D物理效果  J*a 递归快速排序中静态变量的状态管理与陷阱  妖精动漫免费平台 妖精动漫官网资源观看网址  顺丰快递查单号物流信息 顺丰快递小程序查询入口  在J*aScript中复现SciPy的B样条拟合与求值:关键考量  谷歌浏览器最新官方入口链接 谷歌浏览器网页版官网导航  qq游戏手机版下载安装_qq游戏移动端入口  淘宝网网页版登录入口 淘宝官方网页版快捷登录  J*a编写用户注册与登录功能_掌握字符串与验证逻辑  qq音乐在线播放入口_qq音乐电脑版登录链接  Win10如何开启蓝牙功能_Windows10找不到蓝牙开关解决方法  如何使用spryker/configurable-bundles-products-resource-relationship模块解决复杂产品捆绑关系难题  qq邮箱日历功能怎么用_创建日程与会议邀请的技巧  sublime怎么设置启动时打开的窗口_sublime会话管理与热退出  TypeScript/J*aScript:高效查找数组中首个唯一ID对象  192.168.1.1管理中心入口 192.168.1.1路由器网页设置平台  Lar*el头像管理:图片缩放与旧文件删除的最佳实践  字由网在线版登录地址 字由网网页版安全入口  PHP中获取MongoDB服务器运行时间(Uptime)的专业指南  如何创建没有密码的Windows本地账户_跳过微软账户登录的技巧【教程】  在Runstone环境中高效处理TasteDive API的JSON数据  QQ邮箱网页版登录入口 QQ邮箱官方在线使用平台  蛙漫漫画免费阅读入口_蛙漫官方正版无广告纯净版  Node.js 中使用 node-cron 实现定时 API 数据抓取与处理  Python getattr() 异常处理深度解析:避免程序意外退出  黑鲨3Pro怎样在相册开漫画风滤镜_iPhone黑鲨3Pro相册开漫画风滤镜【趣味滤镜】  使用Python高效删除Word宏并转换DOCM为DOCX格式  Golang如何实现容器化日志收集与分析_Golang容器日志收集分析方法  PHP表单数据传递:如何通过隐藏输入字段获取动态ID 

搜索