delega degli eventi e associazione diretta quando si aggiungono elementi complessi a una pagina

Ho alcuni markup come questo (le classi sono solo per la spiegazione):

  1. Top-Line Info
    1. Top-Line Info
      Content A
    1. Content B

Cioè, elenchi ordinabili nidificati. Il plugin ordinabile è sufficiente, tuttavia, poiché ogni li (in seguito “object”) mantiene il suo livello, sebbene gli elenchi interni siano connessi. Gli elementi hanno un’intestazione sempre visibile e una sezione visibile quando sono espansi, triggersti ​​facendo clic sull’intestazione. L’utente può aggiungere e rimuovere elementi da entrambi i livelli a volontà; aggiungendo un elemento di primo livello includerà una lista di nidi vuota al suo interno. La mia domanda riguarda l’inizializzazione JS dell’elemento appena creato: Mentre condivideranno alcune funzionalità comuni, che posso coprire tramite

 $("#root").on("click", "li > header", function() { $(this).parent().toggleClass("collapsed"); }); 

e

 li.collapsed section { display: none; } 

(Domanda a parte: questo sarebbe un posto appropriato per usare i tag HTML5 di dettagli / riepilogo? Sembra quasi incerto sul fatto che anche quelli diventeranno la specifica finale, e voglio una transizione scorrevole, quindi mi sembra di Ho bisogno comunque di JS, ma io rivolgo la domanda alle masse. Ciao, masse.)

Se l’elenco radice è l’unico elemento (rilevante) garantito per essere presente al caricamento della pagina, per .on () per funzionare in modo efficace, devo associare tutti gli eventi a quell’elemento e specificare il selettore preciso per ciascuno, poiché capiscilo. Quindi, per esempio, per bind le funzioni separate a due pulsanti l’uno accanto all’altro, dovrei specificare il selettore per intero ogni volta, à la

 $("#root").on("change", "li > section button.b1", function() { b1Function(); }).on("change", "li > section button.b2", function() { b2Function(); }); 

È esatto? Stando così le cose, ha più senso rinunciare a .on () e bind i miei eventi al momento in cui il nuovo object viene aggiunto alla pagina? Il numero totale di elementi sarà probabilmente al massimo pari a dozzine, se questo fa la differenza nella risposta.

Creerai meno overhead della CPU nel vincolare gli eventi usando $().on(, ) dato che vincolerai a un singolo elemento “root” invece di potenzialmente molti altri singoli elementi discendenti (ogni legatura richiede tempo …).

Detto questo, si verificheranno ulteriori sovraccarichi della CPU quando si verificano gli eventi effettivi in ​​quanto devono far esplodere il DOM all’elemento “root”.

Racconto: delegato salva la CPU durante il binding di gestori di eventi ; bind salva la CPU quando gli eventi si innescano (ad es. un utente fa clic su qualcosa).

Quindi spetta a te decidere quale punto è più importante per le prestazioni. Hai CPU disponibile quando aggiungi i nuovi elementi? In questo caso, il binding diretto ai nuovi elementi sarebbe il migliore per le prestazioni complessive, tuttavia se aggiungere gli elementi è un’operazione che richiede molta CPU, probabilmente si vorrà debind l’associazione degli eventi e lasciare che l’triggerszione dell’evento crei un sovraccarico aggiuntivo della CPU da tutti i bubbling.

Nota che:

 $().on(, , ) 

equivale a:

 $().delegate(, , ) 

e quello:

 $().on(, ) 

equivale a:

 $().bind(, ) 

.on() è nuovo in jQuery 1.7 e se si utilizza 1.7+ allora .delegate(, , ) è solo una scorciatoia per .on(, , ) .

AGGIORNARE

Ecco un test delle prestazioni che indica che è più rapido debind il binding di eventi piuttosto che eseguire il binding a ciascun elemento singolarmente: http://jsperf.com/bind-vs-click/29 . Purtroppo questo test delle prestazioni è stato rimosso.

AGGIORNARE

Ecco un test delle prestazioni che mostra che l’triggerszione degli eventi è più veloce quando esegui il binding diretto agli elementi piuttosto che debind l’associazione: http://jsperf.com/jquery-delegate-vs-bind-triggering (nota che non si tratta di una performance perfetta test poiché i metodi di bind sono inclusi nel test, ma poiché il delegate esegue più velocemente il binding, significa che il bind è ancora più veloce relativamente quando si parla di triggering)

Poiché la risposta accettata ha test non accurati (BTW: testare il codice, misurare le prestazioni, non seguire ciecamente alcune “regole” – non è così che si fa l’ottimizzazione!) Ed è semplicemente sbagliato inserire i test fissi: https: // jsperf.com/jquery-delegate-vs-bind-triggering/49

il che dimostra che un esempio così semplice non ha alcuna differenza tra la delega o l’associazione diretta

Gli unici casi in cui la delega è sempre negativa sono eventi come il movimento del mouse e lo scorrimento – che vengono triggersti ​​x volte al secondo. QUESTO è dove noterete qualsiasi differenza di prestazioni.

Se hai una differenza di 1ms (non succederà, ma questo è solo un esempio) su un singolo evento – come il clic – non lo noterai. Se hai una differenza di 1ms sull’evento che accade 100 volte in un secondo, noterai il consumo della CPU.

Il solo fatto di avere migliaia di elementi non avrà un impatto negativo sulle proprie prestazioni con delega – in realtà – questo è il caso in cui dovrebbero essere utilizzate – per evitare di intasare la CPU quando si collegano migliaia di gestori di eventi.

Quindi, se hai davvero bisogno di una regola da seguire (non farlo), usa la delega su tutto tranne il movimento del mouse, lo scorrimento e altri eventi che puoi aspettarti di sparare continuamente.