Come aggiungere listener di eventi individuali usando jquery .each ()?

Jan 08 2021

Ho una configurazione semplice: due pulsanti con valori diversi. Voglio usare la funzione .each () da jquery per aggiungere un listener di eventi clic a ciascuno dei pulsanti che registra semplicemente i valori di ciascun pulsante. Ma in qualche modo quando si utilizza .each (), jquery sovrascrive il gestore dei clic per i pulsanti precedenti. Questo mi lascia con due domande:

  1. Perché?
  2. Come si aggiungono singoli listener di eventi a una raccolta di oggetti jquery?

Vedere il codice di seguito

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

Risposte

1 RoryMcCrossan Jan 08 2021 at 20:14

Il problema nel codice è perché hai dichiarato implicitamente le variabili typee value, quindi sono windownell'ambito. Pertanto, ogni iterazione successiva sovrascrive i valori in modo che solo i valori finali vengano visualizzati dopo la fine del ciclo.

Per risolvere questo problema, definire le variabili all'interno del ciclo:

$(() => { $(`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>

Tuttavia , non è affatto necessario ileach()ciclo. È possibile risolvere il problema e migliorare la qualità del codice associando lo stesso gestore di eventi a tutti glibuttonelementi e utilizzando latargetproprietà dell'evento che viene sollevata per accedere ai loro attributi.

Inoltre, tieni presente che l'aggiunta di attributi non standard, togglein questo caso, può causare problemi nell'interfaccia utente e JS. Un approccio migliore consiste nell'usare una classe per raggruppare gli elementi.

Infine, onee twonon sono valori validi per l' typeattributo. Utilizza datainvece un attributo per allegare i tuoi metadati personalizzati a un elemento.

Detto questo, prova questo:

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

utilizzare $(this)all'interno del clic di richiamata

$(() => {
  $(`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>

E inoltre non c'è bisogno di menzionare all'interno di ogni callback. Puoi chiamare in modo normale come di seguito

$(() => { $(`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. Perché l'ascoltatore si lega all'ultimo valore di $ toggle.
  2. Creando ed eseguendo una nuova funzione come mostrato nello snippet.

Spiegato meglio in questa domanda .

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