当前位置:首页 > 文章列表 > 文章 > php教程 > jQuery动态计算价格与数量方法

jQuery动态计算价格与数量方法

2025-07-14 20:54:30 0浏览 收藏

知识点掌握了,还需要不断练习才能熟练运用。下面golang学习网给大家带来一个文章开发实战,手把手教大家学习《jQuery动态计算价格与数量教程》,在实现功能的过程中也带大家重新温习相关知识点,温故而知新,回头看看说不定又有不一样的感悟!

使用jQuery实现动态输入框的价格与数量联动计算教程

本教程旨在详细指导如何在Web应用中,利用jQuery实现对动态生成的订单项(如商品名称、单价、数量)进行实时总价计算。我们将探讨如何为动态元素绑定事件监听器,遍历并获取每个项目的单价和数量,最终计算出订单总价,并提供完整的代码示例与优化建议。

在构建在线订餐或购物应用时,一个常见的需求是允许用户动态添加多个商品条目,并实时显示这些条目的总价。这涉及到前端动态元素的生成、数据获取以及实时的数学计算。本教程将以一个典型的订单详情页面为例,详细讲解如何使用jQuery来优雅地解决这一问题。

核心思路:动态计算与事件绑定

问题的核心在于两个方面:

  1. 动态生成元素: 用户可以点击按钮添加新的商品选择行,每行包含商品名称选择框、单价输入框和数量输入框。
  2. 实时总价计算: 当任何一个商品的“数量”发生变化时,系统需要重新计算所有商品的“单价 × 数量”之和,并更新总价显示。

由于商品行是动态添加的,传统的直接事件绑定方式可能无法覆盖到新生成的元素。因此,我们需要采用一种能够处理动态元素的事件绑定策略,并在每次数量变化时,遍历所有商品行进行计算。

实现步骤与代码解析

我们将分步解析HTML结构、PHP后端逻辑以及jQuery前端实现。

HTML结构回顾

订单详情部分通常包含一个容器,用于存放所有商品条目。每个条目包含:

  • 商品名称选择框 (select): 用于选择商品,其值会触发后端请求获取价格。
  • 单价输入框 (input[type="text"]): 显示所选商品的单价,通常为只读。
  • 数量输入框 (input[type="number"]): 用户输入购买数量。
<div class="form-group">
  <label class="control-label col-lg-4"></label>
  <div id="append" class="col-lg-4">
    <!-- 初始的商品条目 -->
    <div id="diva" class="box">
      <header>
        <h5>تفاصيل الطلب</h5>
      </header>
      <div class="body getval">
        <div class="form-group">
          <label class="control-label col-lg-2">الصنف</label>
          <div class="col-lg-10">
            &lt;select id=&quot;itemname&quot; name=&quot;itemname[]&quot; class=&quot;form-control&quot;&gt;
              <option disabled selected>اختر الصنف</option>
              <?php echo getValues($pdo); ?>
            &lt;/select&gt;
          </div>
        </div>
        <div class="form-group">
          <label class="control-label col-lg-2">السعر</label>
          <div class="col-lg-10">
            &lt;input type=&quot;text&quot; id=&quot;price&quot; name=&quot;price[]&quot; placeholder=&quot;-&quot; readonly class=&quot;form-control price&quot;&gt;
          </div>
        </div>
        <div class="form-group">
          <label class="control-label col-lg-2">الكمية</label>
          <div class="col-lg-10">
            &lt;input class=&quot;form-control quantity&quot; type=&quot;number&quot; name=&quot;quantity[]&quot; value=&quot;0&quot; min=&quot;1&quot;&gt;
          </div>
        </div>
      </div>
    </div>
  </div>
  <!-- 总价显示框 -->
  &lt;input type=&quot;text&quot; id=&quot;total&quot; placeholder=&quot;-&quot; readonly class=&quot;form-control&quot;&gt;
</div>
<!-- 添加新行的按钮 (假设有一个ID为'add'的按钮) -->
<button id="add">添加商品</button>

注意,为了方便jQuery选择和操作,我们为价格输入框添加了 price 类,为数量输入框添加了 quantity 类,为总价输入框添加了 total ID。

PHP后端服务

PHP后端(GetPrice.php)负责根据前端传递的商品名称(或ID)从数据库中查询并返回对应的价格。

<?php    
    require 'DBConnection.php'; // 数据库连接
    $code='';
    if(isset($_POST["code"])){
        $id = $_POST["code"];
        // 假设 all_menu 表中包含 item_name 和 price 字段
        $get_c = $pdo->prepare("SELECT price FROM all_menu WHERE `item_name` = :item_name");
        $get_c->bindParam(':item_name', $id); // 使用参数绑定防止SQL注入
        $get_c->execute(); 
        while ($row = $get_c->fetch()) {
            $code .= $row['price'];
        }
        echo $code.'.00'; // 返回价格,格式化为 .00
    }
?>

重要提示: 在实际生产环境中,请务必使用预处理语句和参数绑定来防止SQL注入,如上述代码所示。

jQuery前端逻辑

jQuery代码是实现动态功能的核心。

1. 获取商品价格

当用户选择商品名称时,通过AJAX请求后端获取价格并填充到对应的价格输入框。对于动态添加的行,需要为每个新行单独绑定 change 事件。

// 初始行的事件绑定
$('#itemname').change(function(){
  var code = $(this).val();  
  $.ajax({
    type: 'POST',
    url: 'pages/GetPrice.php',
    data:{code:code},
    success: function(data){
      $('#price').val(data); // 使用jQuery选择器更简洁
      handleQuantityChange(); // 价格更新后也可能影响总价,触发计算
    },
    error: function (jqXHR, textStatus, errorThrown){
      alert(errorThrown);
    }
  });
});
2. 动态添加行

点击“添加商品”按钮时,复制现有HTML结构并插入到页面中,同时为新行的元素赋予唯一的ID(如果需要)。

var nextRowID = 0;
$('#add').click(function(e){
  e.preventDefault();
  var id = ++nextRowID;
  // 构建新的行HTML,注意ID的动态生成
  var newRowHtml = '<div class="form-group"><label class="control-label col-lg-4"></label><div id ="diva'+id+'" class="col-lg-4"><div class="box"><header><h5>تفاصيل الطلب</h5></header><div class="body getval"><div class="form-group"><label class="control-label col-lg-2">الصنف</label><div class="col-lg-10">&lt;select id=&quot;itemname&apos;+id+&apos;&quot; name=&quot;itemname[]&quot; class=&quot;form-control&quot;&gt;<option disabled selected>اختر الصنف</option><?php echo getValues($pdo); ?>&lt;/select&gt;</div></div><div class="form-group"><label class="control-label col-lg-2">السعر</label><div class="col-lg-10">&lt;input type=&quot;text&quot; id=&quot;price&apos;+id+&apos;&quot; name=&quot;price[]&quot; placeholder=&quot;-&quot; readonly class=&quot;form-control price&quot;&gt;</div></div><div class="form-group"><label class="control-label col-lg-2">الكمية</label><div class="col-lg-10">&lt;input class=&quot;form-control quantity&quot; type=&quot;number&quot; name=&quot;quantity[]&quot; value=&quot;0&quot; min=&quot;1&quot;&gt;</div></div></div></div></div></div>';
  $('#append').append(newRowHtml);

  // 为新添加的商品名称选择框绑定事件
  $('#itemname'+id+'').change(function(){
    var code = $(this).val();  
    var currentRowId = $(this).attr('id').replace('itemname', ''); // 获取当前行的ID后缀
    $.ajax({
      type: 'POST',
      url: 'pages/GetPrice.php',
      data:{code:code},
      success: function(data){
        $('#price'+currentRowId+'').val(data);
        handleQuantityChange(); // 价格更新后,重新计算总价
      },
      error: function (jqXHR, textStatus, errorThrown){
        alert(errorThrown);
      }
    });
  });

  // 每次添加新行后,重新绑定或触发数量变化事件
  handleQuantityChange(); 
});
3. 核心:动态总价计算函数

这是解决问题的关键。我们需要一个函数来遍历所有商品行,获取它们的单价和数量,然后计算总和。

function handleQuantityChange(){
  // 解除旧的change事件绑定,然后重新绑定,确保只执行一次
  // 对于动态添加的元素,更推荐使用事件委托(见注意事项)
  $('.quantity').unbind('change').change(function(){
    let totalAmount = 0.0;
    // 遍历所有具有 'price' 类的输入框
    $('.price').each(function(){
      const priceElement = $(this);
      // 找到与当前价格输入框在同一商品行内的数量输入框
      // 这里通过 DOM 结构进行查找:
      // priceElement.parent() -> <div class="col-lg-10"> (价格输入框的父级)
      // .parent() -> <div class="form-group"> (价格输入框的form-group)
      // .next() -> <div class="form-group"> (数量输入框的form-group)
      // .find('.quantity') -> 找到其中的数量输入框
      const quantityElement = priceElement.closest('.form-group').next('.form-group').find('.quantity');

      const price = parseFloat(priceElement.val()) || 0; // 确保是数字,默认为0
      const quantity = parseFloat(quantityElement.val()) || 0; // 确保是数字,默认为0

      totalAmount += price * quantity;
    });
    // 更新总价显示
    $('#total').val(totalAmount.toFixed(2)); // 保留两位小数
  });
  // 首次加载或添加新行后,立即触发一次计算,确保总价是正确的
  // 模拟一次数量变化,以便在页面加载时或新行添加后立即计算总价
  $('.quantity').first().trigger('change');
}

DOM遍历解释:priceElement.closest('.form-group') 向上查找最近的 .form-group 父元素,这是包含价格输入框的整个行容器。 next('.form-group') 找到这个 form-group 的下一个兄弟元素,这通常是包含数量输入框的 form-group。 find('.quantity') 在这个数量的 form-group 中查找 quantity 类。

4. 整合事件监听

在文档加载完成后,以及每次动态添加新行后,都需要调用 handleQuantityChange() 函数,以确保所有当前存在的数量输入框都能正确绑定事件,并且总价能够被实时更新。

$(document).ready(function(){
  // 页面加载完成后,初始化总价计算
  handleQuantityChange();

  // 初始行的商品名称选择事件
  $('#itemname').change(function(){
    var code = $(this).val();  
    $.ajax({
      type: 'POST',
      url: 'pages/GetPrice.php',
      data:{code:code},
      success: function(data){
        $('#price').val(data);
        handleQuantityChange(); // 价格更新后,重新计算总价
      },
      error: function (jqXHR, textStatus, errorThrown){
        alert(errorThrown);
      }
    });
  });

  // 添加新行的按钮点击事件
  var nextRowID = 0;
  $('#add').click(function(e){
    e.preventDefault();
    var id = ++nextRowID;
    // 构建新的行HTML,注意ID的动态生成
    var newRowHtml = '<div class="form-group"><label class="control-label col-lg-4"></label><div id ="diva'+id+'" class="col-lg-4"><div class="box"><header><h5>تفاصيل الطلب</h5></header><div class="body getval"><div class="form-group"><label class="control-label col-lg-2">الصنف</label><div class="col-lg-10">&lt;select id=&quot;itemname&apos;+id+&apos;&quot; name=&quot;itemname[]&quot; class=&quot;form-control&quot;&gt;<option disabled selected>اختر الصulo</option><?php echo getValues($pdo); ?>&lt;/select&gt;</div></div><div class="form-group"><label class="control-label col-lg-2">السعر</label><div class="col-lg-10">&lt;input type=&quot;text&quot; id=&quot;price&apos;+id+&apos;&quot; name=&quot;price[]&quot; placeholder=&quot;-&quot; readonly class=&quot;form-control price&quot;&gt;</div></div><div class="form-group"><label class="control-label col-lg-2">الكمية</label><div class="col-lg-10">&lt;input class=&quot;form-control quantity&quot; type=&quot;number&quot; name=&quot;quantity[]&quot; value=&quot;0&quot; min=&quot;1&quot;&gt;</div></div></div></div></div></div>';
    $('#append').append(newRowHtml);

    // 为新添加的商品名称选择框绑定事件
    $('#itemname'+id+'').change(function(){
      var code = $(this).val();  
      var currentRowId = $(this).attr('id').replace('itemname', '');
      $.ajax({
        type: 'POST',
        url: 'pages/GetPrice.php',
        data:{code:code},
        success: function(data){
          $('#price'+currentRowId+'').val(data);
          handleQuantityChange(); // 价格更新后,重新计算总价
        },
        error: function (jqXHR, textStatus, errorThrown){
          alert(errorThrown);
        }
      });
    });

    // 每次添加新行后,重新绑定或触发数量变化事件
    handleQuantityChange(); 
  });
});

注意事项与优化建议

  1. 事件委托 (Event Delegation): 在 handleQuantityChange 函数中,我们使用了 $('.quantity').unbind('change').change(...) 来重新绑定事件。这种方法在每次添加新行时都会解除并重新绑定所有 .quantity 元素的 change 事件。对于频繁添加新行的场景,这可能导致性能问题。 更推荐的做法是使用事件委托,将事件绑定到父元素上,利用事件冒泡来监听动态子元素的事件。这样,无论何时添加新的 .quantity 元素,事件监听器都无需重新绑定。

    // 优化后的 handleQuantityChange 函数
    function handleQuantityChange() {
      let totalAmount = 0.0;
      // 遍历所有具有 'price' 类的输入框
      $('.price').each(function(){
        const priceElement = $(this);
        const quantityElement = priceElement.closest('.form-group').next('.form-group').find('.quantity');
    
        const price = parseFloat(priceElement.val()) || 0;
        const quantity = parseFloat(quantityElement.val()) || 0;
    
        totalAmount += price * quantity;
      });
      $('#total').val(totalAmount.toFixed(2));
    }
    
    // 在 document ready 中使用事件委托
    $(document).ready(function(){
      // 绑定数量输入框的change事件,使用事件委托
      // 这里的'body'可以替换为更具体的、不会动态变化的父容器
      $('body').on('change', '.quantity', handleQuantityChange);
    
      // 绑定商品名称选择框的change事件,同样使用事件委托
      $('body').on('change', '[name="itemname[]"]', function(){ // 使用name属性选择器更通用
        var code = $(this).val();  
        var currentItemSelect = $(this); // 获取当前触发事件的select元素
        $.ajax({
          type: 'POST',
          url: 'pages/GetPrice.php',
          data:{code:code},
          success: function(data){
            // 找到当前select元素所在行的价格输入框
            currentItemSelect.closest('.form-group').nextAll('.form-group').find('.price').val(data);
            handleQuantityChange(); // 价格更新后,重新计算总价
          },
          error: function (jqXHR, textStatus, errorThrown){
            alert(errorThrown);
          }
        });
      });
    
      // 添加新行的按钮点击事件
      var nextRowID = 0;
      $('#add').click(function(e){
        e.preventDefault();
        var id = ++nextRowID;
        // 构建新的行HTML,注意ID的动态生成
        // 确保新生成的select和input有正确的class和name属性
        var newRowHtml = '<div class="form-group"><label class="control-label col-lg-4"></label><div id ="diva'+id+'" class="col-lg-4"><div class="box"><header><h5>تفاصيل الطلب</h5></header><div class="body getval"><div class="form-group"><label class="control-label col-lg-2">الصنف</label><div class="col-lg-10">&lt;select id=&quot;itemname&apos;+id+&apos;&quot; name=&quot;itemname[]&quot; class=&quot;form-control&quot;&gt;<option disabled selected>اختر الصنف</option><?php echo getValues($pdo); ?>&lt;/select&gt;</div></div><div class="form-group"><label class="control-label col-lg-2">السعر</label><div class="col-lg-10">&lt;input type=&quot;text&quot; id=&quot;price&apos;+id+&apos;&quot; name=&quot;price[]&quot; placeholder=&quot;-&quot; readonly class=&quot;form-control price&quot;&gt;</div></div><div class="form-group"><label class="control-label col-lg-2">الكمية</label><div class="col-lg-10">&lt;input class=&quot;form-control quantity&quot; type=&quot;number&quot; name=&quot;quantity[]&quot; value=&quot;0&quot; min=&quot;1&quot;&gt;</div></div></div></div></div></div>';
        $('#append').append(newRowHtml);
    
        // 添加新行后,触发一次总价计算,以防新行有默认值
        handleQuantityChange(); 
      });
    
      // 页面加载时,首次触发总价计算
      handleQuantityChange();
    });

    使用事件委托后,handleQuantityChange 函数本身不再需要负责绑定事件,它只负责计算逻辑。

  2. 数据类型转换与验证: 在使用 parseFloat() 进行计算时,务必确保输入框的值是有效的数字。如果用户输入了非数字字符,parseFloat() 可能会返回 NaN。在计算前,可以使用 isNaN() 或逻辑或 || 0 来处理这种情况,确保计算结果的正确性。例如:parseFloat(value) || 0。

  3. 用户体验:

    • 初始值: 确保数量输入框有合理的初始值(如 value="1" 或 value="0")。
    • 禁用只读字段: 价格字段设置为 readonly 是一个好习惯,防止用户误修改。
    • 格式化输出: 总价输出时,使用 toFixed(2) 可以确保金额显示为两位小数,符合财务规范。

总结

通过本教程,我们学习了如何利用jQuery处理动态生成的HTML元素,并实现复杂的实时计算逻辑。关键在于理解事件绑定的策略(尤其是事件委托),以及如何在DOM结构中准确地定位相关元素。掌握这些技术,将使您能够构建更加动态、响应式的Web应用。在实际开发中,始终考虑代码的可维护性、性能和用户体验,选择最适合当前场景的实现方式。

本篇关于《jQuery动态计算价格与数量方法》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于文章的相关知识,请关注golang学习网公众号!

AI工具助自媒体0到接单全攻略AI工具助自媒体0到接单全攻略
上一篇
AI工具助自媒体0到接单全攻略
联想笔记本蓝屏0x000000D1怎么解决
下一篇
联想笔记本蓝屏0x000000D1怎么解决
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    511次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    499次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • 千音漫语:智能声音创作助手,AI配音、音视频翻译一站搞定!
    千音漫语
    千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
    685次使用
  • MiniWork:智能高效AI工具平台,一站式工作学习效率解决方案
    MiniWork
    MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
    645次使用
  • NoCode (nocode.cn):零代码构建应用、网站、管理系统,降低开发门槛
    NoCode
    NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
    674次使用
  • 达医智影:阿里巴巴达摩院医疗AI影像早筛平台,CT一扫多筛癌症急慢病
    达医智影
    达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
    691次使用
  • 智慧芽Eureka:更懂技术创新的AI Agent平台,助力研发效率飞跃
    智慧芽Eureka
    智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
    666次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码