在模板标签内部的DOM元素上添加事件监听器

4
假设我在模板中有一个按钮。
<template id="persons">
     <tr>
         <td></td>
         <td></td>
         <td><button type="button" id="delete" class="btn btn-danger">Delete</button></td>
     </tr>
</template>

现在我正在尝试通过以下方式为按钮添加事件监听器:

this.oBtnDel = document.getElementById('delete');

this.oBtnDel.addEventListener("click", somefunc);

然而,我遇到了一个错误:

无法读取 null 的 'addEventListener' 属性

我该如何解决这个问题?


这意味着该按钮尚未被渲染。您可以考虑使用代理。 - Rajesh
在添加监听器时,DOM 中是否有 button 元素可用? - Krishna Prashatt
你打算将那个按钮添加到DOM中吗?建议你在此之后尝试附加事件处理程序。 - Nisarg Shah
3个回答

3

模板中的项目不是常规DOM的一部分。当您绑定事件监听器时,它们不会出现在那里。如果您有多个id为delete的情况,则还将遇到问题,因为id必须是唯一的。

您需要做的是使用事件委托,并使用数据属性来识别按钮。

模板

<template id="persons">
     <tr>
         <td></td>
         <td></td>
         <td><button type="button" data-action="delete" data-objectid="id to delete" class="btn btn-danger">Delete</button></td>
     </tr>
</template>

Javascript

//Bind the event to the parent table say it has an id of parentTable
this.oTable= document.getElementById('parentTable');    
this.oTable.addEventListener("click", function(event){
   //check the delete button was clicked
   if(event.target.dataset.action === "delete")
   {
       //Logic for delete goes here
       var idToDelete = event.target.dataset.objectid;
       /*Rest of your logic*/
   }
});

注意以上代码未经测试。如果不起作用,您应该能够使用提供的链接来填补空白。

关于事件委托的进一步阅读:https://davidwalsh.name/event-delegate


先生,我可以问这一部分吗?如果(event.target.dataset.delete == "delete"),这应该改为if(event.target.dataset.action== "delete")吗? - Beginner
为什么我在event.target.dataset.objectid中得到了null,我只是像这样附加属性:oCRUD.oTd[5].setAttribute("data-objectid", element.id); 在getPerson()中,突然间我就得到了null。 - Beginner
数据属性与常规属性有所不同,最好使用oCRUD.oTd[5].dataset.objectid = element.id; - Jon P
当我在控制台中打印出event.target.dataset时,仍然会得到未定义(undefined)的结果。我只是得到了DOMStringMap { action: "delete" } action: "delete" proto: DOMStringMap,但对象(objectid)没有值。 - Beginner
1
啊,我错过了什么,你将数据属性应用到了 td 而不是按钮上。要将其应用到按钮上,请尝试使用 oCRUD.oTd[5].querySelector("[data-action=delete]").dataset = element.id - Jon P
显示剩余2条评论

2
根据 MDN

HTML 内容模板 (<template>) 元素是一种机制,用于保存 HTML,该 HTML 在页面加载时不会立即呈现,但可以在运行时使用 JavaScript 实例化。

将模板视为内容片段,该片段被存储以供稍后在文档中使用。虽然解析器在加载页面时确实处理了 <template> 元素的内容,但它只是为了确保这些内容有效;然而,元素的内容不会被呈现

当您尝试将事件处理程序附加到按钮时,<template> 的内容尚未呈现。请在将模板包含到元素后再尝试附加事件处理程序。

请参阅下面的代码片段:

var template = document.getElementById("persons");
document.body.appendChild(template.content);

this.oBtnDel = document.getElementById('delete');
this.oBtnDel.addEventListener("click", () => console.log("click"));
<template id="persons">
     <tr>
         <td></td>
         <td></td>
         <td><button type="button" id="delete" class="btn btn-danger">Delete</button></td>
     </tr>
</template>


先生,您能否查看我的整个代码 https://stackoverflow.com/questions/57386589/refresh-table-after-a-successful-axios-post-request?noredirect=1#comment101256726_57386589? - Beginner

-1

试试这样做。

 <script> 
        document.getElementById("delete").addEventListener("click", function(){ 
        // Write your function here
    }); 
        </script> 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接