jQuery实现发票输入框总额求和功能失效问题求助
问题分析与解决方案
你的求和功能失效的核心原因是:求和代码只在页面初始化时执行了一次,后续修改商品数量或单价计算单条总价时,并没有重新触发求和逻辑。另外,你的事件绑定还存在闭包陷阱(虽然你说第一个功能正常,但实际可能只有最后一行的输入会正确触发计算,其他行可能有隐藏问题)。
下面是修复后的完整代码,我会一步步说明改进点:
1. 封装求和函数
把求和逻辑抽成独立函数,这样可以在需要的时候随时调用,确保每次数据变化都能重新计算小计:
function calculateSubtotal() { let sum = 0; $(".inp-prod-total").each(function(){ // 解析输入值,非数字默认按0处理,避免NaN干扰求和 const itemTotal = parseFloat($(this).val()) || 0; if(!isNaN(itemTotal)) { sum += itemTotal; } }); // 保留两位小数,符合金额显示的规范 $("#inv_subtotal").val(sum.toFixed(2)); }
2. 修复事件绑定的闭包问题 + 实时触发求和
原来的var i会导致所有keyup事件共享同一个i变量,最终只会绑定到最后一行的元素上。改用let i(ES6语法)可以解决这个闭包陷阱,同时给单价输入框也绑定事件(修改单价也应该重新计算单条总价和小计),并且每次计算单条总价后立即调用求和函数:
<script type="text/javascript"> // 页面初始化时先计算一次小计,确保加载时就显示正确数值 calculateSubtotal(); // 用let确保每个循环迭代的i是独立变量,解决闭包陷阱 for (let i = 0; i < <?=$index?>; i++) { // 数量输入框keyup事件 $("#quantity_"+i).keyup(function(){ const quantity = parseFloat($("#quantity_"+i).val()) || 0; const price = parseFloat($("#price_"+i).val()) || 0; const total = quantity * price; $("#total_"+i).val(total.toFixed(2)); // 计算完单条总价后立即更新发票小计 calculateSubtotal(); }); // 新增单价输入框keyup事件,避免修改单价后不更新总价和小计 $("#price_"+i).keyup(function(){ const quantity = parseFloat($("#quantity_"+i).val()) || 0; const price = parseFloat($("#price_"+i).val()) || 0; const total = quantity * price; $("#total_"+i).val(total.toFixed(2)); calculateSubtotal(); }); } </script>
3. 额外优化建议
- 给金额、数量输入框添加
type="number"属性,限制用户只能输入数字,减少无效输入:<?= $form->field($invoiceItem, '['.$index.']product_price')->textInput(['id'=> 'price_'.$index , 'class' => '', 'type' => 'number', 'step' => '0.01'])->label(false) ?> <?= $form->field($invoiceItem, '['.$index.']product_qtt')->textInput(['id'=> 'quantity_'.$index , 'class' => '', 'type' => 'number', 'step' => '1'])->label(false) ?> - 可以额外添加
blur事件,确保用户用鼠标离开输入框时,也能触发计算,提升体验。
这样修改后,无论是页面初始化,还是修改商品数量/单价,都会实时更新单条商品总价和发票小计了。
内容的提问来源于stack exchange,提问作者Bynd
相关产品推荐
相关产品推荐

