jQuery动态生成的select选中值无法触发事件如何解决
问题根因
动态生成的行下拉框不触发事件,是三个低级错误导致的:
- 给
.sell绑定change事件时用了直接绑定,这种方式只能匹配页面初始加载时就存在的元素,后续动态插入的.sell节点没有绑定事件,自然不会触发逻辑 - 动态生成的元素重复使用了
mySelect、comments_remove等id,HTML规范要求id在页面中全局唯一,重复id会导致元素获取永远命中第一个节点,逻辑完全混乱 - 额外写的
genfun函数存在上下文错误:内联onchange调用时函数内this指向window,根本拿不到当前触发事件的select节点,属于冗余无效代码
修复后完整代码
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="table-responsive"> <table class="table table-review review-table mb-0" id="table_achievements"> <thead> <tr> <th style="width:40px;">序号</th> <th>字段</th> <th>匹配规则</th> <th>匹配值</th> <th>逻辑符</th> <th style="width:92.56px;">操作</th> </tr> </thead> <tbody id="table_achievements_tbody"> <tr> <td>1</td> <td> <select class="form-control"> <option>Field Name</option> <option>Div Awada</option> <option>Div Vlad</option> </select> </td> <td> <select class="form-control"> <option>Equals</option> <option>Greater than</option> <option>Less than</option> </select> </td> <td><input type="text" class="form-control" placeholder="Enter Value" ></td> <td style="width: 120px;"> <select class="form-control sell" name="argSelect" > <option value="Arg">Argument</option> <option value="AND">AND</option> <option value="OR">OR</option> <option value="ONLY">ONLY</option> </select> </td> <td></td> </tr> </tbody> </table> </div> <script> $(function () { // 事件委托绑定到永久存在的父级tbody,覆盖所有动态生成的.sell节点 $('#table_achievements_tbody').on('change', '.sell', function () { const $currentSelect = $(this); const $table = $currentSelect.closest("table.table-review"); const tableId = $table.attr('id'); const selectVal = $currentSelect.val(); if(selectVal === "AND" || selectVal === "OR"){ const $newRow = $("<tr />"); $newRow.html(buildNewRow(tableId)); $("#"+tableId+"_tbody").append($newRow); // 当前行已经选过逻辑符,禁用对应选项避免重复触发生成多行 $currentSelect.find('option[value="AND"], option[value="OR"]').prop('disabled', true); } }); // 删除按钮同样用事件委托,用class选择器替代重复id $('#table_achievements_tbody').on("click", ".comments_remove", function () { const $currentRow = $(this).closest("tr"); const $prevRow = $currentRow.prev(); // 恢复上一行的逻辑符可选项、显示删除按钮 $prevRow.find('.sell option').prop('disabled', false); $prevRow.find('td:last-child').html('<button type="button" class="btn btn-danger comments_remove"><i class="fa fa-trash-o"></i></button>'); $currentRow.remove(); // 重新计算行号 refreshRowIndex(); }); // 构建新行内容,移除所有重复id和内联事件 function buildNewRow(table_id) { const tbody = document.getElementById(table_id).getElementsByTagName("tbody")[0]; const rowIndex = tbody.getElementsByTagName("tr").length + 1; return ` <td>${rowIndex}</td> <td> <select name="DynamicTextBox" class="select form-control"> <option>Field Name</option> <option>Div Awada</option> <option>Div Vlad</option> </select> </td> <td> <select name="DynamicTextBox" class="select form-control"> <option>Field Name</option> <option>Equals</option> <option>Greater than</option> </select> </td> <td><input type="text" name="DynamicTextBox" class="form-control" placeholder="Enter Value"></td> <td> <select class="form-control sell" name="argSelect"> <option value="Arg">Argument</option> <option value="AND">AND</option> <option value="OR">OR</option> <option value="ONLY">ONLY</option> </select> </td> <td><button type="button" class="btn btn-danger comments_remove"><i class="fa fa-trash-o"></i></button></td> ` } // 刷新行号 function refreshRowIndex(){ $('#table_achievements_tbody tr').each(function(index){ $(this).find('td:first').text(index+1); }) } }); </script>
修改点说明
- 所有动态元素的事件统一用jQuery事件委托绑定到初始就存在的
tbody节点上,不管后续新增多少行,事件都能正常触发 - 移除所有重复id和内联onchange绑定,删除冗余的
genfun函数,逻辑统一收敛 - 新增逻辑符选项禁用逻辑,选完AND/OR生成新行后,当前行的AND/OR选项会被禁用,避免重复选导致无限新增行
- 新增行号刷新逻辑,删除行后序号自动重排,不会出现序号错乱
- 删除行时自动恢复上一行的逻辑符可选状态和删除按钮,交互更合理
内容的提问来源于stack exchange,提问作者nodedata
相关产品推荐
相关产品推荐

