如何为含交互内容的动态创建div添加事件监听器
动态加载元素的事件委托问题与解决方案
当搜索如何为动态加载的div绑定事件监听器时,公认方案是事件委托(event delegation),使用insertAdjacentHTML添加HTML时未找到其他可行方法。
我通过如下方式向DOM中添加div:
HTML
<div id="container"> </div>
CSS
.card{ background: rosybrown; text-align: center; width: 50%; } h2{ margin-top: 0; }
JavaScript
document.getElementById('container').insertAdjacentHTML( 'beforeend', `<div class="card"> <div class="card-header">Card header content</div> <div class="card-body"> <h2>Card body</h2> <select> <option value="value1">Value 1</option> </select><br> Some more text </div> </div>` ); // Event delegation document.addEventListener('click', function (e) { console.log(e.target.className); });
点击卡片任意位置可在控制台看到输出。我了解事件委托是将点击事件绑定到document这类父元素,通过对比点击元素的className等属性执行操作。但问题在于event.target指向卡片内的具体元素,无法获取整个card父元素以执行用户操作(如跳转至详情页)。曾考虑用<a>标签包裹div,但会导致select等交互元素失效。
解决方案
感谢@epascarello、@KooiInc等人的解答!我需要仅在未点击交互元素(如select)时触发card的事件,因此做了如下修改,目前效果良好:
HTML
<div id="container"> </div>
CSS
.card{ background: rosybrown; text-align: center; width: 50%; } h2{ margin-top: 0; }
JavaScript
document.getElementById('container').insertAdjacentHTML( 'beforeend', `<div class="card" data-id="1"> <div class="card-header">Card header content</div> <div class="card-body"> <h2>Card body</h2> <select> <option value="value1">Value 1</option> </select><br> Some more text </div> </div>` ); // Event delegation document.addEventListener('click', function (e) { console.clear(); const card = e.target.closest('.card'); if (card && e.target.tagName !== 'SELECT'){ console.log('Redirect to ' + card.dataset.id); } });
若有比使用e.target.tagName手动排除元素更高效的方法,欢迎提出建议。
内容的提问来源于stack exchange,提问作者Samuel Gfeller
相关产品推荐
相关产品推荐

