Im Browser -DOM -Ereignis werden einige Ereignisse kontinuierlich mit den Vorgängen des Benutzers ausgelöst. Beispiel: Die Größe des Browserfensters ändern, scrollen Sie die Browser -Seite und Mousemove. Das heißt, wenn der Benutzer diese Browseroperationen auslöst, wird diese Methode kontinuierlich ausgelöst, wenn die entsprechende Ereignishandhabungsmethode an das Skript gebunden ist.
Dies ist nicht das, was wir wollen, denn manchmal, wenn die Ereignisbearbeitungsmethode relativ groß ist, werden DOM -Operationen wie komplex und ständig die Ereignisse ausgelöst, was zu einem Rückgang der Benutzererfahrung führt (langsame UI -Reaktion, Browser festgefahren usw.). Normalerweise fügen wir dem entsprechenden Ereignis Logik hinzu, um die Ausführung zu verzögern.
Im Allgemeinen verwenden wir den folgenden Code, um diese Funktion zu implementieren:
var count = 0; Funktion testfn () {console.log (count ++); } // Wenn der Browser die Größe // 1. Löschen Sie den vorherigen Timer // 2. Fügen Sie einen Timer hinzu, um den realen Funktionstestfn um 100 Millisekunden zu verzögern, um das Fenster zu auslösen. Clearimeout (Timer); timer = setTimeout (function () {testfn ();}, 100);};Sorgfältige Schüler werden feststellen, dass der obige Code tatsächlich falsch ist. Dies ist ein Problem, das Anfänger machen werden: Der Rückgabewert der SetTimeout -Funktion sollte in einer relativen globalen Variablen gespeichert werden, da sonst jedes Mal ein neuer Timer generiert wird, wenn die Größe der Größe geändert wird, wodurch der von uns gesendete Effekt nicht erzielt wird.
Also haben wir den Code geändert:
var timer = null; window.onResize = function () {ClearTimeOut (Timer); timer = setTimeout (function () {testfn ();}, 100);};Zu diesem Zeitpunkt ist der Code normal, aber es gibt ein weiteres neues Problem - ein globaler variabler Timer wird generiert. Das wollen wir nicht sehen. Wenn diese Seite andere Funktionen hat, wird sie auch als Timer bezeichnet. Verschiedene Codes verursachen zuvor Konflikte. Um dieses Problem zu lösen, müssen wir eine Sprachfunktion von JavaScript: Verschlusssschluss verwenden. Leser können über verwandte Wissen in MDN lernen. Der geänderte Code lautet wie folgt:
/*** Funktionsdrosselungsmethode* @param Funktion Fn Delay -Aufruffunktion* @param number Verzögerung Wie lang ist die Verzögerung* @return Funktionsmethode zur Verzögerung der Ausführung*/var throttle = Funktion (fn, delay) {var timer = null; return function () {ClearTimeout (Timer); timer = setTimeout (function () {fn ();}, delay); }}; window.onResize = throttle (testfn, 200, 1000);Wir verwenden eine Verschlussfunktion (Drosselklappenrosselung), um den Timer intern zu setzen und die Verzögerungsverarbeitungsfunktion zurückzugeben. Auf diese Weise ist die Timer -Variable außen unsichtbar, aber die Timer -Variable kann auch zugegriffen werden, wenn die interne Verzögerungsfunktion ausgelöst wird.
Natürlich ist diese Schreibmethode für Anfänger nicht einfach zu verstehen. Wir können die Schreibmethode ändern, um zu verstehen:
var throttle = function (fn, delay) {var timer = null; return function () {ClearTimeout (Timer); timer = setTimeout (function () {fn ();}, delay); }}; var f = throttle (testfn, 200); window.onResize = function () {f ();};Hier ist ein Standpunkt: Die Funktion, die nach dem Rufen des Gass zurückgegeben wird, ist die tatsächliche Funktion, die aufgerufen werden muss, wenn die OnResize ausgelöst wird
Jetzt scheint es, dass diese Methode nahezu Perfektion ist, aber bei der tatsächlichen Verwendung nicht der Fall. Zum Beispiel:
Wenn der Benutzer ständig die Größe der Browserfenster ändert
Daher müssen wir eine weitere Funktion hinzufügen: Wenn der Benutzer die Größe der Größe auslöst, sollte er mindestens einmal innerhalb eines bestimmten Zeitraums ausgelöst werden. Da es innerhalb eines bestimmten Zeitraums liegt, kann diese Beurteilungsbedingung die aktuelle Zeit Millisekunden in Anspruch nehmen und jeder Funktionsaufruf die aktuelle Zeit der letzten Anrufzeit subtrahiert. Wenn der Unterschied größer als eine bestimmte Zeitspanne ist, wird sie direkt gesendet, da sie sonst immer noch die Logik für die Zeitleitungsverzögerung folgt.
Was im folgenden Code hingewiesen werden muss, lautet:
1. Die Funktion früherer Variablen ähnelt der des Timers. Beide werden die letzte Kennung aufgezeichnet und müssen relative globale Variablen sein.
2. Wenn der Logikprozess der Logik "mindestens einmal ausgelöst" folgt, muss der Funktionsaufruf abgeschlossen werden, um die vorherige Zeit zurückzusetzen. Einfach ausgedrückt, ist es: Im Vergleich zum nächsten letzten Mal ist es tatsächlich die aktuelle.
/*** Funktionsdrosselungsmethode* @Param Funktion Fn Delay Call -Funktion* @param number Verzögerung Wie lang ist die Verzögerung* @param -Nummer, wie lange sie ausgelöst ist var vorher = null; return function () {var now = +new Date (); if (! vorher) vorher = jetzt; if (jetzt - vorher> zumindest) {fn (); // Setzen Sie die letzte Startzeit bis zur Endzeit dieser Zeit zurück } else {ClearTimeout (Timer); timer = setTimeout (function () {fn ();}, delay); }}};üben:
Wir simulieren eine Szene des Drossels, wenn ein Fenster scrolls, dh wenn der Benutzer die Seite nach unten scrolliert, müssen wir einige Methoden drosseln, z. B. die Berechnung der DOM -Position usw., die einen kontinuierlichen Betrieb von DOM -Elementen erfordert.
Der vollständige Code lautet wie folgt:
<! DocType html> <html Lang = "en"> <head> <meta charset = "utf-8"> <title> drosseltell </title> </head> <body> <div style = "Höhe: 5000px"> <div id = "Demo" style = "Position: Fixed; document.getElementById ('Demo'); Funktion testfn () {Demo.innerHtml += 'testfn wurde' ++ count +'Zeit <br>';} var throttle = Funktion (fn, delay, mindestens) {var timer = null; var vorher = null; return function () {var now = +new Date (); if (! vorher) vorher = jetzt; if (mindestens && jetzt - vorher> mindestens) {fn (); // Setzen Sie die letzte Startzeit bis zur Endzeit dieser Zeit zurück Clearimeout (Timer); } else {ClearTimeout (Timer); Timer = setTimeout (function () {fn (); vorher = null;}, delay); }}}}; window.oncroll = throttle (testfn, 200); // window.oncroll = throttle (testfn, 500, 1000); </script> </body> </html>Wir verwenden zwei Fälle, um den Effekt zu testen, nämlich zumindest das zumindest zumindest das Hinzufügen zumindest und nicht zum Hinzufügen:
// Fall 1Window.OnScroll = Throttle (testfn, 200); // Fall 2Window.onscroll = Throttle (testfn, 200, 500);
Fall 1 manifestiert sich als: Testfn wird während des Bildlaufvorgangs nicht aufgerufen (kann nicht gestoppt werden) und wird einmal aufgerufen, bis es gestoppt wird, was bedeutet, dass der letzte SetTimeout in der Drosselklappe ausgeführt wird und der Effekt wie in der Abbildung gezeigt ist (siehe das ursprüngliche GIF -Bild):
Fall 2 manifestiert sich als: Während des Bildlaufvorgangs (kann nicht gestoppt werden) wird TestFN zum ersten Mal um 500 ms verzögert (aus mindestens Verzögerungslogik) und dann mindestens alle 500 ms ausführen. Der Effekt ist wie in der Abbildung dargestellt
Bisher wurden die Ergebnisse, die wir erzielen möchten, im Grunde genommen abgeschlossen. Die Leser können über einige nachfolgende Hilfsoptimierungen nachdenken, wie z.
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.