获取动态生成DOM元素并绑定点击事件报错的问题咨询
动态生成元素绑定点击事件失效的解决思路
问题描述
点击按钮触发函数生成表格内容,给表格内的<td>设置id="clickme"后尝试获取元素并绑定点击事件,触发报错:
Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
问题原因
- 元素未生成时提前获取:页面加载时就执行
document.querySelector('#clickme'),但此时<td>还未通过按钮点击生成,因此获取到null,绑定事件自然失败。 - 重复id违反规范:循环生成多个
<td>都使用同一个id="clickme",HTML要求id必须唯一,这会导致后续元素的id无效,也不利于元素选择。
解决方法
方法一:事件委托(推荐)
利用事件冒泡机制,把点击事件绑定到已经存在的父元素(如表格的<tbody>)上,通过判断触发事件的目标元素来执行逻辑。同时将重复的id改为class,符合规范。
修改后的JavaScript代码:
const select = document.querySelector('#select') const show = document.querySelector('#show') const table = document.querySelector('#table') const btn = document.querySelector('#send') const arr = [{ name: 'Mark', alter: 22, }, { name: 'Emil', alter: 33, }, { name: 'Sohab', alter: 64, }, ] btn.addEventListener('click', () => { table.innerHTML = '' arr.forEach((info) => { // 用class代替重复的id table.innerHTML += ` <tr> <td class="clickme bg bg-info">${info.name}</td> <td>${info.alter}</td> </tr> ` }) }) // 事件委托绑定到父元素table table.addEventListener('click', (e) => { // 判断点击的是目标元素 if (e.target.classList.contains('clickme')) { alert('TEST clickme') } })
方法二:生成元素时直接绑定事件
不使用innerHTML拼接字符串,而是通过DOM API创建元素,在元素生成后立即绑定点击事件。
修改后的JavaScript代码:
const select = document.querySelector('#select') const show = document.querySelector('#show') const table = document.querySelector('#table') const btn = document.querySelector('#send') const arr = [{ name: 'Mark', alter: 22, }, { name: 'Emil', alter: 33, }, { name: 'Sohab', alter: 64, }, ] btn.addEventListener('click', () => { table.innerHTML = '' arr.forEach((info) => { const tr = document.createElement('tr') const tdName = document.createElement('td') tdName.className = 'bg bg-info' tdName.textContent = info.name // 生成元素后直接绑定事件 tdName.addEventListener('click', () => { alert('TEST clickme') }) const tdAlter = document.createElement('td') tdAlter.textContent = info.alter tr.appendChild(tdName) tr.appendChild(tdAlter) table.appendChild(tr) }) })
内容的提问来源于stack exchange,提问作者Samee
相关产品推荐
相关产品推荐

