Как добавить отдельных прослушивателей событий с помощью jquery .each ()?

Jan 08 2021

У меня простая настройка: две кнопки с разными значениями. Я хочу использовать функцию .each () из jquery, чтобы добавить прослушиватель событий щелчка к каждой из кнопок, который просто регистрирует значения каждой кнопки. Но каким-то образом при использовании .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>

Ответы

1 RoryMcCrossan Jan 08 2021 at 20:14

Проблема в вашем коде, потому что вы неявно объявлять typeи valueпеременные, поэтому они находятся в 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в этом случае может привести к проблемам в пользовательском интерфейсе и JS. Лучше всего использовать класс для группировки элементов.

Наконец, oneи twoнедопустимые значения для 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>

1 prasanth Jan 08 2021 at 20:10

использовать $(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>

Kostas Jan 08 2021 at 20:11
  1. Поскольку слушатель привязывается к последнему значению $ toggle.
  2. Создав и запустив новую функцию, как показано во фрагменте.

Объясните лучше в этом вопросе .

<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>