为何使用outerHTML时按钮的onClick事件无法触发?
按钮绑定事件后通过outerHTML拼接失效的问题解决
问题代码
serviceQuerySnapshot.forEach(doc => { if(ownerIdNo === doc.data().shooter_id){ const servViewButton = document.createElement("button"); servViewButton.innerHTML = '<i class="fa fa-eye" aria-hidden="true"></i>'; servViewButton.style.marginRight = "5px"; servViewButton.style.border = "0"; servViewButton.style.background = "transparent"; servViewButton.onclick = async function() { alert("wow"); console.error(); } const servArrItem = ` · ${doc.data().name} ${servViewButton.outerHTML} ${'<br>'}`; servArr += servArrItem; } });
问题原因
用outerHTML把DOM元素转换成HTML字符串时,元素上绑定的JS事件会完全丢失。因为outerHTML只生成元素的纯HTML代码,不会保留任何JS层面的事件绑定(不管是onclick赋值还是addEventListener添加的监听)。当你把这个字符串插入到页面后,新生成的按钮只是一个普通的HTML元素,没有绑定任何事件,所以点击不会触发alert。
解决方案
方案1:直接操作DOM元素(推荐)
不要通过字符串拼接的方式组装内容,而是直接创建DOM节点,把文本和按钮都添加到容器元素中,再将容器插入到页面或存入数组。这样事件绑定会被完整保留。
serviceQuerySnapshot.forEach(doc => { if(ownerIdNo === doc.data().shooter_id){ const servViewButton = document.createElement("button"); servViewButton.innerHTML = '<i class="fa fa-eye" aria-hidden="true"></i>'; servViewButton.style.marginRight = "5px"; servViewButton.style.border = "0"; servViewButton.style.background = "transparent"; servViewButton.onclick = async function() { alert("wow"); console.error(); } // 创建容器包裹文本和按钮 const itemContainer = document.createElement("div"); // 添加文本内容 itemContainer.textContent = ` · ${doc.data().name}`; // 追加按钮 itemContainer.appendChild(servViewButton); // 追加换行 itemContainer.appendChild(document.createElement("br")); // 如果servArr是DOM元素数组,直接push servArr.push(itemContainer); // 如果要直接插入页面,替换成下面的代码 // document.getElementById('your-target-container').appendChild(itemContainer); } });
方案2:使用事件委托(适合必须用字符串拼接的场景)
如果因为某些原因必须用字符串拼接HTML,可以给按钮添加自定义属性,然后在父容器上通过事件委托监听点击事件,判断点击目标是按钮时执行逻辑。
// 先给父容器绑定事件委托(确保父容器已经存在于页面) document.getElementById('parent-container').addEventListener('click', async function(e) { // 找到点击的按钮(考虑到按钮内的i标签,用closest匹配) const targetBtn = e.target.closest('button[data-doc-id]'); if(targetBtn) { const docId = targetBtn.dataset.docId; alert("wow"); console.error(); // 这里可以根据docId获取对应的文档数据做后续操作 } }); // 拼接HTML字符串时给按钮添加自定义属性 serviceQuerySnapshot.forEach(doc => { if(ownerIdNo === doc.data().shooter_id){ // 直接拼接按钮的HTML,加入data-doc-id属性标记文档 const buttonHtml = `<button style="margin-right:5px;border:0;background:transparent;" data-doc-id="${doc.id}"><i class="fa fa-eye" aria-hidden="true"></i></button>`; const servArrItem = ` · ${doc.data().name} ${buttonHtml} <br>`; servArr += servArrItem; } }); // 最后把拼接好的字符串插入父容器 document.getElementById('parent-container').innerHTML = servArr;
内容的提问来源于stack exchange,提问作者Dionico Noe C. Alegarbes
相关产品推荐
相关产品推荐

