JavaScript中添加第二个事件处理器后首个回调函数失效的原因排查
问题出在哪?
你遇到的第一个事件处理器失效的坑,根源是用innerHTML +=更新父元素内容的操作会销毁并重建父元素内的所有DOM节点!
当你执行document.getElementById("parent").innerHTML += "<div id='plot_"+i+"'></div>"时,浏览器其实是把parent里现有的所有内容转成字符串,拼上新内容后再重新解析成DOM节点替换回去。这个过程中,第一个plot里的select元素是被完全删掉再重建的,可新生成的元素并没有重新绑定之前的事件监听器,所以第一个事件就彻底失效了。
怎么解决?
别用innerHTML +=了,改用原生DOM操作来添加新元素——直接创建div节点,再append到父元素里,这样只会新增节点,不会碰已经存在的DOM结构,之前绑定的事件自然能保留。
修改你的processJson函数就行,其他代码不用动:
function processJson(outputJson) { // 先缓存父元素,避免重复查DOM,提升性能 const parentContainer = document.getElementById("parent"); for (var i in outputJson) { let divIDForPlot = "plot_" + i; // 用createElement创建新的div,设置id后添加到父元素 const plotDiv = document.createElement('div'); plotDiv.id = divIDForPlot; parentContainer.appendChild(plotDiv); let item = outputJson[i]; let type = item["outputType"]; if (type == "plot") { processPlot(divIDForPlot, item); } else if (type == "table") { // 这里可以加table的处理逻辑 } } }
改完之后会怎么样?
现在再运行代码,第一个plot的下拉框change事件会正常打印日志,第二个的也能正常工作,两个事件处理器不会互相影响啦。
另外提个小建议:processPlot里给plot元素设置additionalHtml的时候,因为是首次创建内部元素,用innerHTML没问题,但如果之后还要动态更新这些元素,最好也用DOM操作,避免重绘带来的意外问题。
内容的提问来源于stack exchange,提问作者Kival M
相关产品推荐
相关产品推荐

