动态添加表格行后change事件重复触发的解决方案求助
解决jQuery动态添加元素重复触发change事件的问题
问题场景
动态添加表格行时,为.gettotal类的输入框绑定change事件,但修改任意输入框的值时,会多次触发该事件,期望仅触发当前输入框对应的事件。
问题根源
每次点击.addnewjewel按钮添加新行时,都执行了$(".gettotal").change(...)——这会给所有已存在的.gettotal元素(包括之前添加的行里的输入框)重复绑定一次change事件。比如添加第2行时,第1行的输入框会被第二次绑定事件,修改时就会触发2次;添加第3行时,前两行的输入框各多一次绑定,以此类推,导致事件触发次数随添加行数递增。
解决方案
方案1:事件委托(推荐)
利用jQuery的事件委托机制,将事件绑定到静态存在的父元素(比如表格的tbody.addnewjewelbody),只绑定一次即可覆盖所有现有和未来添加的.gettotal元素,从根本上避免重复绑定。
修改后的完整代码:
$(document).ready(function(){ // 事件委托:绑定到父元素,监听子元素的change事件 $(".addnewjewelbody").on("change", ".gettotal", function(){ console.log("changed"); var grosstotal = 0; var weight = $(this).val(); console.log(weight); }); $(".addnewjewel").click(function(){ $(".addnewjewelbody").append(` <tr id="${newjewelid}"> <td><input type="text" name="jewelname" id="jewelname"></td> <td> <input type="radio" id="Gold${newjewelid}" name="jeweltype+${newjewelid}"> <label for="Gold${newjewelid}">Gold</label> <input type="radio" name="jeweltype+${newjewelid}" id="Silver${newjewelid}"> <label for="Silver${newjewelid}">Silver</label> </td> <td><input type="number" class="gettotal" name="newjewelweight" value="0" min="0" id="newjewelweight+${newjewelid}" step="0.01"></td> <td><input type="number" class="gettotal" name="currentrate" value="0" min="0" id="currentrate+${newjewelid}"></td> <td><input type="number" class="gettotal" name="makinhcharge" value="0" min="0" id="makinhcharge+${newjewelid}"></td> <td><input type="number" class="gettotal" name="othercharge" value="0" min="0" id="othercharge+${newjewelid}"></td> <td><input type="number" class="gettotal" name="GrossCharge" value="0" min="0" id="grosscharge+${newjewelid}"></td> <td></td> </tr> `); newjeweladded.push(newjewelid); newjewelid++; console.log(newjewelid); console.log(newjeweladded); }); });
方案2:仅给新添加的元素绑定事件
如果不想用事件委托,可以在添加新行后,只针对当前新行内的.gettotal元素绑定事件,而非全局选择所有.gettotal。
修改点击事件内的绑定代码:
$(".addnewjewel").click(function(){ // 先append新行 $(".addnewjewelbody").append(` <tr id="${newjewelid}"> <td><input type="text" name="jewelname" id="jewelname"></td> <td> <input type="radio" id="Gold${newjewelid}" name="jeweltype+${newjewelid}"> <label for="Gold${newjewelid}">Gold</label> <input type="radio" name="jeweltype+${newjewelid}" id="Silver${newjewelid}"> <label for="Silver${newjewelid}">Silver</label> </td> <td><input type="number" class="gettotal" name="newjewelweight" value="0" min="0" id="newjewelweight+${newjewelid}" step="0.01"></td> <td><input type="number" class="gettotal" name="currentrate" value="0" min="0" id="currentrate+${newjewelid}"></td> <td><input type="number" class="gettotal" name="makinhcharge" value="0" min="0" id="makinhcharge+${newjewelid}"></td> <td><input type="number" class="gettotal" name="othercharge" value="0" min="0" id="othercharge+${newjewelid}"></td> <td><input type="number" class="gettotal" name="GrossCharge" value="0" min="0" id="grosscharge+${newjewelid}"></td> <td></td> </tr> `); newjeweladded.push(newjewelid); // 仅给当前新行的.gettotal绑定事件 $(`#${newjewelid} .gettotal`).change(function(){ console.log("changed"); var grosstotal = 0; var weight = $(this).val(); console.log(weight); }); newjewelid++; console.log(newjewelid); console.log(newjeweladded); });
说明
- 事件委托是更优方案,只需绑定一次事件,性能更好,代码更简洁,适合频繁动态添加元素的场景。
- 方案2虽然也能解决问题,但每次添加元素都要执行一次绑定逻辑,相比委托机制稍显冗余。
内容的提问来源于stack exchange,提问作者Abhi
相关产品推荐
相关产品推荐

