将事件附加到javascript中的动态元素

IT技术 javascript
2021-01-26 05:51:33

我正在尝试将 html 数据动态插入到动态创建的列表中,但是当我尝试为动态创建的按钮附加 onclick 事件时,该事件不会触发。解决方案将不胜感激。

Javascript代码:

document.addEventListener('DOMContentLoaded', function () {
   document.getElementById('btnSubmit').addEventListener('click', function () {
        var name = document.getElementById('txtName').value;
        var mobile = document.getElementById('txtMobile').value;
        var html = '<ul>';
        for (i = 0; i < 5; i++) {
            html = html + '<li>' + name + i + '</li>';
        }
        html = html + '</ul>';

        html = html + '<input type="button" value="prepend" id="btnPrepend" />';
        document.getElementsByTagName('form')[0].insertAdjacentHTML('afterend', html);
    });

    document.getElementById('btnPrepend').addEventListener('click', function () {
        var html = '<li>Prepending data</li>';
        document.getElementsByTagName('ul')[0].insertAdjacentHTML('afterbegin', html);
    });
});

HTML代码:

<form>
    <div class="control">
        <label>Name</label>
        <input id="txtName" name="txtName" type="text" />
    </div>
    <div class="control">
        <label>Mobile</label>
        <input id="txtMobile" type="text" />
    </div>
    <div class="control">
        <input id="btnSubmit" type="button" value="submit" />
    </div>
</form>
6个回答

这是因为您的元素是动态创建的。您应该使用事件委托来处理事件。

 document.addEventListener('click',function(e){
    if(e.target && e.target.id== 'brnPrepend'){
          //do something
     }
 });

jquery 使它更容易:

 $(document).on('click','#btnPrepend',function(){//do something})

这是一篇关于事件委托事件委托的文章

考虑添加一个额外的等号 (===) 以防止意外的类型强制
2021-03-11 05:51:33
但有时它在 iphone 上不起作用,甚至“父”元素也不是动态创建的。这是示例,它适用于所有浏览器,但不适用于 iphone(safary 甚至 chrome)。我不明白为什么。
2021-03-17 05:51:33
谢谢!有时纯 JS 解决方案在 iphone 上不起作用,但如果在另一个父 div 上更改文档,例如,它可以工作。委托的最佳解决方案是什么?
2021-03-19 05:51:33
@Kholiavko 我会说只要“父”元素不是动态创建的,它就应该可以工作。我会将事件处理程序绑定到动态 create d 元素的第一个父元素,以便不同事件处理程序之间没有冲突
2021-04-03 05:51:33
@Kholiavko 这只是因为 codepen 使用沙箱来包装所有内容。如果您真的在普通页面中编写这些代码,它将起作用
2021-04-07 05:51:33

有一种解决方法是捕获点击document.body,然后检查事件目标。

document.body.addEventListener( 'click', function ( event ) {
  if( event.target.id == 'btnSubmit' ) {
    someFunc();
  };
} );
哇,这太棒了,节省了大量时间和代码!:)
2021-03-14 05:51:33
注意: event.srcElement 已弃用。建议改用 event.target。
2021-03-26 05:51:33
或最近的集装箱
2021-03-29 05:51:33
完美答案!
2021-04-08 05:51:33

您必须在插入元素之后附加事件,就像您不在插入元素上附加全局事件document而是在插入元素上附加特定事件一样。

例如

document.getElementById('form').addEventListener('submit', function(e) {
  e.preventDefault();
  var name = document.getElementById('txtName').value;
  var idElement = 'btnPrepend';
  var html = `
    <ul>
      <li>${name}</li>
    </ul>
    <input type="button" value="prepend" id="${idElement}" />
  `;
  /* Insert the html into your DOM */
  insertHTML('form', html);
  /* Add an event listener after insert html */
  addEvent(idElement);
});

const insertHTML = (tag = 'form', html, position = 'afterend', index = 0) => {
  document.getElementsByTagName(tag)[index].insertAdjacentHTML(position, html);
}
const addEvent = (id, event = 'click') => {
  document.getElementById(id).addEventListener(event, function() {
    insertHTML('ul', '<li>Prepending data</li>', 'afterbegin')
  });
}
<form id="form">
  <div>
    <label for="txtName">Name</label>
    <input id="txtName" name="txtName" type="text" />
  </div>
  <input type="submit" value="submit" />
</form>

此方法仅适用于 CSR(客户端渲染)。这不适用于 SSR(服务器端渲染)。为了使其同时适用于 CSR 和 SSR,事件委托是解决方案:javascript document.addEventListener('click',function(e){ if(e.target && e.target.id== 'brnPrepend'){ //do something } });
2021-03-12 05:51:33
但出于性能原因,这种方法更好。所以这取决于你的用例。
2021-03-31 05:51:33

区别在于您如何在 DOM 中创建和附加元素。

如果您通过 来创建元素document.createElement,请添加一个事件侦听器,并将其附加到 DOM。你的事件会触发。

如果您将元素创建为这样的字符串:html += "<li>test</li>"`,则元素在技术上只是一个字符串。字符串不能有事件监听器。

一种解决方案是创建每个元素,document.createElement然后直接将它们添加到 DOM 元素。

// Sample
let li = document.createElement('li')
document.querySelector('ul').appendChild(li)

你可以做类似的事情:

// Get the parent to attatch the element into
var parent = document.getElementsByTagName("ul")[0];

// Create element with random id
var element = document.createElement("li");
element.id = "li-"+Math.floor(Math.random()*9999);

// Add event listener
element.addEventListener("click", EVENT_FN);

// Add to parent
parent.appendChild(element);