Chrome / jQuery Uncaught RangeError: Maximale Größe des Aufrufstapels überschritten

113

Ich erhalte die Fehlermeldung "Nicht erfasster RangeError: Maximale Aufrufstapelgröße überschritten" auf Chrome. Hier ist meine jQuery-Funktion

$('td').click(function () {
        if ($(this).context.id != null && $(this).context.id != '') {
            foo($('#docId').val(), $(this).attr('id'));
        }
        return false;
    });

Beachten Sie, dass die Seite Zehntausende von Zellen enthält. Im Allgemeinen verbinde ich Stapelüberläufe jedoch mit Rekursion, und in diesem Fall gibt es, soweit ich sehen kann, keine.

Erzeugt das Erstellen eines solchen Lambda automatisch eine Menge Material auf dem Stapel? Gibt es einen Weg daran vorbei?

Im Moment besteht die einzige Problemumgehung darin, die Onclick-Ereignisse beim Rendern des HTML-Codes explizit für jede Zelle zu generieren, wodurch der HTML-Code viel größer wird.

Andy
quelle
2
Sind Sie sicher, dass die foo-Funktion nicht wiederholt wird? Tritt der Fehler immer noch auf, wenn Sie diesen Funktionsaufruf entfernen?
etw
1
Funktioniert es in anderen Browsern wie erwartet? Tritt dieser Fehler auf, wenn Sie die foo($('#docId').val(), $(this).attr('id'));Zeile kommentieren ? - Zusätzlicher Leistungstipp: Zwischenspeichern Sie das Ergebnis von Selektoren. Behalten Sie beispielsweise das Ergebnis von $(this)in einer Variablen bei und verwenden Sie es dann nach Bedarf für Ihren Handler.
WTK
Ich habe ein ähnliches Problem, benötige aber Mouseenter-Ereignisse. Wenn ich Körper oder Tisch benutze, bekomme ich nicht genug Ereignisse.
Ericlaw

Antworten:

133

Da "die Seite Zehntausende von Zellen enthält" das Binden des Klickereignisses an jede einzelne Zelle ein schreckliches Leistungsproblem verursacht. Es gibt einen besseren Weg, dies zu tun, indem Sie ein Klickereignis an den Körper binden und dann herausfinden, ob das Zellenelement das Ziel des Klicks war. So was:

$('body').click(function(e){
       var Elem = e.target;
       if (Elem.nodeName=='td'){
           //.... your business goes here....
           // remember to replace $(this) with $(Elem)
       }
})

Diese Methode erledigt Ihre Aufgabe nicht nur mit dem nativen "td" -Tag, sondern auch mit dem später angehängten "td". Ich denke, Sie werden an diesem Artikel über Event Binding & Delegate interessiert sein


Oder Sie können einfach die " .on () " - Methode von jQuery mit demselben Effekt verwenden:

$('body').on('click', 'td', function(){
        ...
});
vantrung -cuncon
quelle
danke, wir kämpfen sowieso um die Leistung, also ist das eine großartige Idee :-)
Andy
59
Nein, benutze nicht .live () !!! bitovi.com/blog/2011/04/… Verwenden Sie ein .delegate () (oder .on (), wenn Ihre jQuery neu genug ist) und delegieren Sie von der Tabellenebene aus und nicht vom gesamten Dokument. Dies verbessert Ihre Leistung erheblich mehr als nur die Verwendung von .live (), das im Wesentlichen nur vom gesamten Dokument nach unten delegiert.
Brandwaffel
18
Und .live wurde aus jQuery 1.9
cpuguy83
37

Sie können diesen Fehler auch erhalten, wenn Sie eine Endlosschleife haben. Stellen Sie sicher, dass Sie keine endlosen, rekursiven Selbstreferenzen haben.

John Durden
quelle
6
Das hat mein Problem gelöst. Ich hatte ein <a id="linkDrink" onclick="drinkBeer();">Drink</a>und ein $('#linkDrink').click();in drinkBeer().
Aycan Yaşıt
7

Meins war eher ein Fehler. Was passiert ist, war ein Loop-Klick (ich denke). Im Grunde genommen wurde durch Klicken auf das Login auch das übergeordnete Element angeklickt, was dazu führte, dass die maximale Größe des Aufrufstapels überschritten wurde.

$('.clickhere').click(function(){
   $('.login').click();
});

<li class="clickhere">
  <a href="#" class="login">login</a>
</li>
Jsonras
quelle
3

Dieses Problem trat bei mir auf, als ich jQUery Fancybox in einer Website mit vielen anderen jQuery-Plugins verwendete. Wenn ich die LightBox ( Seite hier ) anstelle von Fancybox verwendet habe, ist das Problem behoben.

Silvio Delgado
quelle
1

Du kannst verwenden

  $(document).on('click','p.class',function(e){
   e.preventDefault();
      //Code 
   });
demenvil
quelle
0

Ich bin kürzlich auch auf dieses Problem gestoßen. Ich hatte eine sehr große Tabelle im Dialog div. Es waren> 15.000 Zeilen. Als die .empty () im Dialog div aufgerufen wurde, wurde der obige Fehler angezeigt.

Ich habe eine Rundum-Lösung gefunden, bei der ich, bevor ich das Dialogfeld bereinige, jede zweite Zeile aus der sehr großen Tabelle entferne und dann .empty () aufrufe. Es schien jedoch funktioniert zu haben. Es scheint, dass meine alte Version von JQuery nicht mit so großen Elementen umgehen kann.

dev4life
quelle