【问题标题】:How to add individual event listeners using jquery .each()?如何使用 jquery .each() 添加单个事件侦听器?
【发布时间】:2021-01-08 13:06:16
【问题描述】:

我有一个简单的设置:两个具有不同值的按钮。我想使用 jquery 中的 .each() 函数向每个按钮添加一个单击事件侦听器,该侦听器仅记录每个按钮的值。 但不知何故,当使用 .each() 时,jquery 会覆盖前一个按钮的单击处理程序。 这给我留下了两个问题:

  1. 这是为什么呢?
  2. 如何将单个事件侦听器添加到 jquery 对象集合中?

见下方代码

  <html lang="en">
    
    <head>
        <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
        <script>
            $(() => {
                $(`button[toggle]`).each((_, button) => {
                    let $toggle = $(button);
                    type = $toggle.attr("type");
                    value = $toggle.attr("value");
                    $toggle.on("click", () => {
                        console.log(type, value);
                    });
                });
            });
        </script>
    
    </head>
    
    <body>
        <div>
            <button toggle type="one" value="true">One</button>
            <button toggle type="two" value="false">Two</button>
        </div>
    </body>
    
    </html>

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    代码中的问题是因为您隐式声明了typevalue 变量,因此它们在window 范围内。因此,每次后续迭代都会覆盖这些值,以便在循环结束后只能看到最终值。

    要解决这个问题,请在循环中定义变量

    $(() => {
      $(`button[toggle]`).each((_, button) => {
        let $toggle = $(button);
        let type = $toggle.attr("type");
        let value = $toggle.attr("value");
        $toggle.on("click", () => {
          console.log(type, value);
        });
      });
    });
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <div>
      <button toggle type="one" value="true">One</button>
      <button toggle type="two" value="false">Two</button>
    </div>

    然而,您根本不需要each() 循环。您可以通过将相同的事件处理程序绑定到所有 button 元素并使用引发的事件的 target 属性来访问它们的属性来解决此问题并提高代码质量。

    此外,请注意添加您自己的非标准属性,在这种情况下为toggle,可能会导致 UI 和 JS 出现问题。更好的方法是使用类对元素进行分组。

    最后,onetwo 不是 type 属性的有效值。改用 data 属性将您自己的自定义元数据附加到元素。

    说了这么多,试试这个:

    jQuery($ => {
      $('.toggle').on('click', e => {
        let $toggle = $(e.target);
        let type = $toggle.data("type"); 
        let value = $toggle.prop("value");
        console.log(type, value);
      });
    });
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <div>
      <button class="toggle" data-type="one" value="true">One</button>
      <button class="toggle" data-type="two" value="false">Two</button>
    </div>

    【讨论】:

      【解决方案2】:

      在点击回调中使用$(this)

      $(() => {
        $(`button[toggle]`).each((_, button) => {
          $(button).on("click", function(){
             type   = $(this).attr("type");
             value  = $(this).attr("value");
            console.log(type, value);
          });
        });
      });
      <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
      
      <button toggle type="one" value="true">One</button>
      <button toggle type="two" value="false">Two</button>

      而且也无需在每个回调中提及。你可以像下面这样正常调用

      $(() => {
        $(`button[toggle]`).on("click", function(){
             type   = $(this).attr("type");
             value  = $(this).attr("value");
            console.log(type, value);
          });
      });
      <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
      
      <button toggle type="one" value="true">One</button>
      <button toggle type="two" value="false">Two</button>

      【讨论】:

      • 谢谢,这是迄今为止最优雅的答案 - 问题:为什么我不能使用匿名函数,即 () => {} 作为点击处理程序?
      • 可以,这个答案只是改变了处理程序定义的格式
      • 因为如果你使用 ES6 Arrow 方法,jquery 在点击回调中有它自己的函数调用,你需要传递像 event 这样的参数。 if 为空 this 不工作。那为什么更喜欢 jquery 中的函数调用。 reference
      • @RoryMcCrossan 。是的,你是对的。但是当元素单击调用时,jquery 有一个默认的循环行为。这就是为什么我更喜欢普通的点击调用而不是循环点击事件
      【解决方案3】:
      1. 因为监听器绑定到 $toggle 的最后一个值。
      2. 通过创建并运行新函数,如 sn-p 所示。

      this question 中解释得更好。

      <html lang="en">
          
          <head>
              <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
              <script>
                  $(() => {
                      $(`button[toggle]`).each((_, button) => {
                          let $toggle = $(button);
                          type = $toggle.attr("type");
                          value = $toggle.attr("value");
                          $toggle.on("click", ((type, value) => {
                            return () => {
                              console.log(type, value);
                            };
                          })(type, value));
                      });
                  });
              </script>
          
          </head>
          
          <body>
              <div>
                  <button toggle type="one" value="true">One</button>
                  <button toggle type="two" value="false">Two</button>
              </div>
          </body>
          
          </html>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-24
        • 2021-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多