【问题标题】:How can I add an event listener for multiple buttons with same class name?如何为具有相同类名的多个按钮添加事件侦听器?
【发布时间】:2014-07-13 03:54:33
【问题描述】:

我正在用 JavaScript 构建决策树。我没有可用于该项目的 jQuery。

我希望能够有按钮,放置在决策树的任何位置(隐藏或显示在页面上的任何位置),具有相同的类名。然后 JS 端的监听器会运行一个函数。

这是我使用的基于 ID 的侦听器。它运作良好,但我需要能够有多个具有相同类或名称的按钮可用。虽然我见过这样的例子,但我无法让它正常工作。

function q1a1() {
var q1a1button = document.getElementById("q1answer1");
        if(q1a1button.addEventListener){
q1a1button.addEventListener("click", function() { q1answer1();}, false);
        } else if(q1a1button.attachEvent){
q1a1button.attachEvent("onclick", function() { q1answer1();});
}
};

if(window.addEventListener){
    window.addEventListener("load", q1a1, false);
        } else if(window.attachEvent){
    window.attachEvent("onload", q1a1);
        } else{
    document.addEventListener("load", q1a1, false);                
}

function q1answer1() {          

//DO SOME STUFF
                                            }

这也需要在尽可能多的 IE 版本中工作。对于单类处理,我使用的是 querySelectorAll。

【问题讨论】:

  • 只需使用 querySelectorAll() 来遍历具有该类的元素,或多或少地将该循环包装在您已有的代码周围。您还可以将单个事件附加到主体,并查看 (e.target||e.srcElement).className 以决定如何在调用时处理事件。
  • querySelectorAll 在 ie8 中工作。如果您需要支持以下任何内容,我为您感到抱歉。只需遍历元素数组,为每个元素添加一个事件监听器。

标签: javascript listener


【解决方案1】:

如果你没有 jquery:

if (document.body.addEventListener){
    document.body.addEventListener('click',yourHandler,false);
}
else{
    document.body.attachEvent('onclick',yourHandler);//for IE
}

function yourHandler(e){
    e = e || window.event;
    var target = e.target || e.srcElement;
    if (target.className.match(/keyword/))
    {
        //an element with the keyword Class was clicked
    }
}

如果你使用像 jquery 这样的跨浏览器库:

HTML:

<div class="myClass">sample</div>
<div class="myClass">sample 2</div>

JS:

function theFuncToCall(event){
  //func code
}

$(document).on('click', '.myClass', theFuncToCall);

【讨论】:

  • jQuery 在此组织内不可用。 (我不能使用它)因此感到沮丧和新的学习曲线。 :)
  • 必须链接到You Might Not Need jQuery :)
【解决方案2】:

你真正要找的是JavaScript Event Delegation。在您的情况下,您有 BUTTON 元素,我将假设它们是 &lt;button&gt; 标签。现在您想知道何时单击其中一个按钮然后运行函数:

if (document.addEventListener) {
    document.addEventListener("click", handleClick, false);
}
else if (document.attachEvent) {
    document.attachEvent("onclick", handleClick);
}

function handleClick(event) {
    event = event || window.event;
    event.target = event.target || event.srcElement;

    var element = event.target;

    // Climb up the document tree from the target of the event
    while (element) {
        if (element.nodeName === "BUTTON" && /foo/.test(element.className)) {
            // The user clicked on a <button> or clicked on an element inside a <button>
            // with a class name called "foo"
            doSomething(element);
            break;
        }

        element = element.parentNode;
    }
}

function doSomething(button) {
    // do something with button
}

页面上出现&lt;button class="foo"&gt;...&lt;/button&gt; 元素的任何地方,单击它或其中的任何HTML 标记,都会运行doSomething 函数。

更新:由于使用了事件委托,因此文档对象上只注册了一个单击处理程序。如果由于 AJAX 调用而创建了更多 &lt;button&gt;s,则您不必在这些新的 &lt;button&gt;s 上注册单击处理程序,因为我们利用了从用户单击的元素冒泡的单击事件文档对象本身。

【讨论】:

  • jQuery 的on 方法非常方便,但是对于我们这些没有jQuery 或者不想使用它的人,我写了Oxydizr,它利用了HTML5 data-* 属性。它允许您完全解耦行为、标记和样式。
  • @Greg Burghardt 如果您希望单击的按钮颜色发生变化,我们如何在没有唯一 id 或类名的情况下实现这一点?
  • 我正在寻找一种提取事件目标的方法。你的代码向我展示了如何做到这一点。非常感谢。这非常有帮助。
【解决方案3】:
var buttons = document.querySelectorAll(".MyClassName");
var i = 0, length = buttons.length;
for (i; i < length; i++) {
    if (document.addEventListener) {
        buttons[i].addEventListener("click", function() {
            // use keyword this to target clicked button
        });
    } else {
        buttons[i].attachEvent("onclick", function() {
            // use buttons[i] to target clicked button
        });
    };
};

【讨论】:

    【解决方案4】:

    这个答案有点矫枉过正,但它应该向您展示如何以“现代”方式构建代码,即使您仍然针对旧浏览器

    1. 编写代码以添加事件侦听器,以便新旧浏览器之间的差异最小

      var listen = (function () { // will return the handler for use in unlisten
          if (window.addEventHandler) {
              return function (node, type, handler) {
                  node.addEventListener(type, handler);
                  return handler;
              };
          } else if (window.attachEvent) {
              return function (node, type, handler) {
                  var fn = function (e) {
                      if (!e) {
                          e = window.event;
                      }
                      if (!e.target && e.srcElement) {
                          e.target = e.srcElement;
                      }
                      return handler.call(this, e);
                  };
                  node.attachEvent('on' + type, fn);
                  return fn;
              };
          } else {
              throw new Error('Events not supported in this environment');
              // or
           // return function ... node['on' + type] = function () { ... };
          }
      }());
      

      如果你也想反过来

      var unlisten = (function () { // use handler given by listen
          if (window.removeEventListener) {
              return function (node, type, handler) {
                  node.removeEventListener(type, handler);
              };
          } else if (window.detachEvent) {
              return function (node, type, handler) {
                  node.detachEvent('on' + type, handler);
              };
          } else {
              throw new Error('Events not supported in this environment');
              // or
           // return function ... node['on' + type] = null;
          }
      }());
      
    2. 编写您的点击处理程序

      function clickHandler(e) {
          // do stuff
      }
      
    3. 将您的点击处理程序包装在一个函数中,以选择仅点击具有正确类的按钮

      function wrappedClickHandler(e) {
          var tokens, i;
          if (e.target.tagName !== 'INPUT' && e.target.tagName !== 'BUTTON') {
              return;
          }
          tokens = (e.target.className || '').split(' ');
          for (i = 0; i < tokens.length; ++i) {
              if (tokens[i] === 'theClassTokenWeWant') {
                  return clickHandler.call(this, e);
                  // or
               // return clickHandler.call(e.target, e);
              }
          }
      }
      
    4. 将此作为侦听器添加到公共祖先节点

      var h = listen(document, 'click', wrappedClickHandler);
      // .. later, if desired
      unlisten(document, 'click', h);
      

    【讨论】:

      【解决方案5】:

      编写事件委托函数的更简单的方法是将其添加到按钮的容器中吗?例如,

      // Select Container Element
      const questionContainer = document.querySelector(".container");
      
      // Listen For Clicks Within Container
      questionContainer.onclick = function (event) {
          // Prevent default behavior of button
          event.preventDefault();
      
          // Store Target Element In Variable
          const element = event.target;
      
          // If Target Element Is a Button
          if (element.nodeName === 'BUTTON') {
              // Event Code
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-08-21
        • 1970-01-01
        • 1970-01-01
        • 2021-12-13
        • 1970-01-01
        • 2020-12-29
        • 2021-03-21
        • 2015-02-04
        • 2022-01-12
        相关资源
        最近更新 更多