代码之家  ›  专栏  ›  技术社区  ›  Syden

动态按钮上的JS事件侦听器

  •  1
  • Syden  · 技术社区  · 8 年前

    想知道为什么在添加多个动态按钮时,他们的切换bg颜色监听器无法持续工作。

    如果我添加3个按钮,按钮1的侦听器(&3将起作用,而按钮2将不起作用。

    //document.ready
    function ready(fn) {
      if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") {
        fn();
      } else {
        document.addEventListener('DOMContentLoaded', fn);
      }
    }
    
    //event listener on dynamic buttons not in DOM
    ready(function() {
      document.querySelector('.makeB').addEventListener('click', function() {
        var btn = document.createElement("button");
        var t = document.createTextNode("toggle bg");
        btn.appendChild(t);
        document.body.appendChild(btn);
        btn.classList.add('elis');
    
        var newBtns = document.querySelectorAll('.elis');
        newBtns.forEach(function(i) {
          i.addEventListener('click', function() {
            document.body.classList.toggle('bg');
          })
        })
      })
    })
    .bg {
      background: red;
    }
    <button class="makeB">create button</button>

    研究了一点冒泡&查看事件委派选项是否有帮助(类似于jquery方法 $(document).on( eventName, selector, function(){} ); 但没有运气)

    如何使动态按钮始终工作?当前场景有什么问题?

    请仅使用JS(无jQuery)。

    3 回复  |  直到 8 年前
        1
  •  2
  •   Sergej    8 年前

    //document.ready
    function ready(fn) {
      if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") {
        fn();
      } else {
        document.addEventListener('DOMContentLoaded', fn);
      }
    }
    
    //event listener on dynamic buttons not in DOM
    ready(function() {
      document.querySelector('.makeB').addEventListener('click', function() {
        var btn = document.createElement("button");
        var t = document.createTextNode("toggle bg");
        btn.appendChild(t);
        document.body.appendChild(btn);
        btn.classList.add('elis');
        btn.addEventListener('click', function() {
          document.body.classList.toggle('bg');
        })
      })
    })
    .bg {
      background: red;
    }
    <button class="makeB">create button</button>
        2
  •  1
  •   Matus Dubrava    8 年前

    简化代码的另一种方法是使用事件委派。只需添加 click 事件侦听器连接到body或其他一些封闭容器(可能是最近的容器),并仅在以下情况下执行其代码 event.target 是你的按钮之一。

    这样,您将跳过将事件侦听器反复添加到相同按钮的部分。

    function ready(fn) {
      if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") {
        fn();
      } else {
        document.addEventListener('DOMContentLoaded', fn);
      }
    }
    
    document.body.addEventListener('click', event => {
      if (event.target.className === 'elis') {
        document.body.classList.toggle('bg');
      }
    });
    
    ready(function() {
      document.querySelector('.makeB').addEventListener('click', function() {
        const btn = document.createElement("button");
        btn.textContent = "toggle bg";
        btn.classList.add('elis')
        document.body.appendChild(btn);
      })
    })
    .bg {
      background: red;
    }
    <button class="makeB">create button</button>
        3
  •  1
  •   dtanders    8 年前

    他们确实在工作。问题是,每次添加按钮时都会添加更多的侦听器,因此只有当某个特定按钮上有奇数个侦听器时,这些侦听器才看起来有效。只需在按钮中添加一个侦听器,然后再将其放入文档中。