使用JS删除HTML元素问题:动态生成行无法删除【附JSFiddle】
这是个前端开发里非常常见的小坑——你用$('.deleteEnv').click(...)绑定事件的方式,只能给页面初始化时就已经存在的DOM元素生效。但你的.deleteEnv按钮是通过点击Add按钮动态生成的,这些元素在页面刚加载时根本不存在,所以事件绑定自然就失效了。
推荐解决方案:使用jQuery事件委托
事件委托是最优雅高效的处理方式,它利用DOM的事件冒泡机制,把事件绑定到一个已经存在的父元素上,再指定触发事件的目标子元素。这样不管子元素是一开始就有的,还是后来动态生成的,事件都能被正常捕获到。
修改你的删除事件代码为:
// 把事件委托给已经存在的#envVariablesDiv父元素 $('#envVariablesDiv').on('click', '.deleteEnv', function() { // 优化:把每一组环境变量包在row里,删除时直接移除整个组 $(this).closest('.row').remove(); });
同时建议你调整动态添加元素的代码,把每一组环境变量的三个col-sm-*元素包在一个.row容器里——这样不仅删除逻辑更清晰,也更符合Bootstrap的布局规范:
$('#addEnv').click(function() { $('#envVariablesDiv').append(` <div class="row"> <div class="col-sm-5 top10"> <div class="input-group"> <label class="input-group-addon">Name</label> <input class="form-control" name="envName[]" type="text" placeholder="e.g. name1" /> </div> </div> <div class="col-sm-5 top10"> <div class="input-group"> <label class="input-group-addon">Variable</label> <input class="form-control" name="envVar[]" type="text" placeholder="e.g. var1" /> </div> </div> <div class="col-sm-2 top10"> <button type="button" class="btn btn-danger deleteEnv"> <span class="fa fa-trash"></span> Delete </button> </div> </div> `); });
(另外注意:你原来的代码给动态生成的input加了重复的id="envName"和id="envVar",这违反了HTML规范——id必须唯一,所以我去掉了这些重复id;同时把name改成数组形式envName[],这样提交表单时能正确获取多组变量的值)
完整可运行代码
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <style> .top10 { margin-top: 10px; } .top20 { margin-top: 20px; } </style> <button id="addEnv" class="btn btn-primary">Add Environment Variable</button> <div id="envVariablesDiv" class="container top20"> </div> <script> $('#addEnv').click(function() { $('#envVariablesDiv').append(` <div class="row"> <div class="col-sm-5 top10"> <div class="input-group"> <label class="input-group-addon">Name</label> <input class="form-control" name="envName[]" type="text" placeholder="e.g. name1" /> </div> </div> <div class="col-sm-5 top10"> <div class="input-group"> <label class="input-group-addon">Variable</label> <input class="form-control" name="envVar[]" type="text" placeholder="e.g. var1" /> </div> </div> <div class="col-sm-2 top10"> <button type="button" class="btn btn-danger deleteEnv"> <span class="fa fa-trash"></span> Delete </button> </div> </div> `); }); // 事件委托绑定删除事件 $('#envVariablesDiv').on('click', '.deleteEnv', function() { $(this).closest('.row').remove(); }); </script>
(我补充了Bootstrap和Font Awesome的CDN,确保样式和图标能正常显示,还加了简单的间距样式)
为什么原来的代码不行?
$('.deleteEnv').click(...)是直接给当前匹配到的元素绑定事件,而页面加载时.deleteEnv元素还不存在,所以没有任何元素被绑定事件。而事件委托是把事件绑定到父元素,当点击子元素时,事件会冒泡到父元素,父元素再判断触发事件的是不是目标子元素,这样就能完美处理动态生成的元素了。
内容的提问来源于stack exchange,提问作者qweq

