Primero, entendamos qué es el acelerador
1. Definición
Si aprieta el grifo hasta que el agua fluya en forma de gotas de agua, encontrará que de vez en cuando, una gota de agua fluirá.
Es decir, un ciclo de ejecución se establece por adelantado, y cuando el momento en que se llama la acción es mayor o igual al ciclo de ejecución, la acción se ejecuta y luego se ingresa el siguiente ciclo nuevo.
Definición de la interfaz:
* Cuando el control de frecuencia devuelve la función se llama continuamente, la frecuencia de ejecución de la acción se limita a tiempos/ retraso* @param retraso {número} tiempo de retraso, unidad milisegundos* @param acción {function} solicita la función asociada, y la función que debe llamarse en la aplicación real* @return {function} devuelve la función de llamadas del cliente*/ throttle (retraso, acción))2. Implementación simple
Var Throttle = Function (Delay, Action) {var Last = 0Return Function () {var Curr = +new Date () if (Curr - Last> Delay) {Action.apply (this, Arguments) Last = Curr}}}Permítanme explicar esta función de estrangulamiento cuidadosamente a continuación.
En el evento DOM del navegador, algunos eventos se activarán continuamente con las operaciones del usuario. Por ejemplo: cambie el tamaño de la ventana del navegador, desplácese la página del navegador y mouseMove. Es decir, cuando el usuario desencadena estas operaciones del navegador, si el método de manejo de eventos correspondiente está vinculado al script, este método se activará continuamente.
Esto no es lo que queremos, porque a veces si el método de manejo de eventos es relativamente grande, las operaciones DOM, como el complejo, y activar constantemente tales eventos causarán pérdidas de rendimiento, lo que dará como resultado una disminución en la experiencia del usuario (respuesta de interfaz de usuario lenta, navegador atascado, etc.). Por lo tanto, generalmente agregaremos lógica al evento correspondiente para retrasar la ejecución.
En términos generales, usamos el siguiente código para implementar esta función:
var count = 0; function testfn () {console.log (count ++); } // Cuando el navegador cambia de tamaño // 1. Borre el temporizador anterior // 2. Agregue un temporizador para retrasar la función real testfn por 100 milisegundos para activar ventana.onresize = function () {var timer = null; ClearTimeOut (temporizador); timer = setTimeOut (function () {testfn ();}, 100);};Los estudiantes cuidadosos descubren que el código anterior es realmente incorrecto. Este es un problema que los novatos hará: el valor de retorno de la función SetTimeOut debe guardar en una variable global relativa, de lo contrario, se generará un nuevo temporizador cada vez que se redimense el tamaño del tamaño, lo que no logrará el efecto que enviamos.
Entonces modificamos el código:
var timer = null; window.onresize = function () {cleartimeout (temporizador); timer = setTimeOut (function () {testfn ();}, 100);};En este momento, el código es normal, pero hay otro problema nuevo: se genera un temporizador variable global. Esto es algo que no queremos ver. Si esta página tiene otras funciones, también se llama temporizador. Los diferentes códigos causarán conflictos antes. Para resolver este problema, necesitamos usar una función de idioma de JavaScript: cierres de cierres. Los lectores pueden aprender sobre el conocimiento relacionado en MDN. El código modificado es el siguiente:
/*** Método de limitación de función* @param Fn Fn Letter Llamado Función* @param Número Retraso ¿Cuánto tiempo es el método de función de retraso? Función de retorno () {ClearTimeOut (temporizador); timer = setTimeOut (function () {fn ();}, demora); }}; window.onresize = Throttle (testfn, 200, 1000);Utilizamos una función de cierre (acelerador) para poner el temporizador internamente y devolver la función de procesamiento de retraso. De esta manera, la variable del temporizador es invisible para el exterior, pero también se puede acceder a la variable del temporizador cuando se activa la función de retraso interna.
Por supuesto, este método de escritura no es fácil de entender para los novatos. Podemos cambiar el método de escritura para comprender:
var del acelerador = function (fn, demora) {var timer = null; Función de retorno () {ClearTimeOut (temporizador); timer = setTimeOut (function () {fn ();}, demora); }}; var f = Throttle (testfn, 200); window.onresize = function () {f ();};Aquí hay un punto de vista: la función devuelta por el acelerador después de ser llamada es la función real que debe llamarse cuando se activa el OnResize
Ahora parece que este método está cerca de la perfección, pero no es el caso en el uso real. Por ejemplo:
Si el usuario cambia constantemente el tamaño de la ventana del navegador, la función de procesamiento de retraso no se ejecutará una vez
Por lo tanto, necesitamos agregar otra función: cuando el usuario cambia de tamaño, debe activarse al menos una vez dentro de un cierto período de tiempo. Dado que está dentro de un cierto período de tiempo, esta condición de juicio puede tomar los milisegundos de tiempo actual, y cada llamada de función resta el tiempo actual desde el último tiempo de llamada, y luego juzga que si la diferencia es mayor que un cierto período de tiempo, se enviará directamente, de lo contrario, aún seguirá la lógica de retraso de tiempo de espera.
Lo que hay que señalar en el siguiente código es:
La función de la variable anterior es similar a la del temporizador. Ambos son los identificadores que registran la última vez y deben ser variables globales relativas
Si el proceso lógico sigue la lógica "activada al menos una vez", entonces la llamada de función debe completarse para restablecer la hora anterior a la hora actual. En resumen, en realidad es el actual en comparación con la próxima vez.
/*** Método de limitación de función* @param FN FN DELATO Función de llamada* @param Retraso de número ¿Cuánto tiempo es el retraso* @param Número al menos cuánto tiempo se desencadena* @@return de la función Método para retrasar la ejecución*/var del acelerador = function (fn, demora, al menos) {var timer = null; var anterior = nulo; function de return () {var now = +new Date (); if (! anterior) anterior = ahora; if (ahora - anterior> al menos) {fn (); // reinicie la última hora de inicio a la hora final de este tiempo anterior = ahora; } else {ClearTimeOut (temporizador); timer = setTimeOut (function () {fn ();}, demora); }}};práctica:
Simulamos una escena de estrangulamiento cuando una ventana se desplaza, es decir, cuando el usuario se desplaza la página hacia abajo, necesitamos estrangular algunos métodos, como: calcular la posición DOM, etc., que requiere un funcionamiento continuo de elementos DOM.
El código completo es el siguiente:
<! Doctype html> <html lang = "en"> <fead> <meta charset = "utf-8"> <title> throttle </title> </head> <body> <div style = "altura: 5000px"> <Div Id = "Demo" Style = "Posición: fijo;"> </div> </div> <script> Var Count = 0, Demo = document.getElementById ('demo'); La función testfn () {Demo.innerhtml += 'testfn se llamó' ++ Count +'Time <br>';} var del acelerador = function (fn, demora, al menos) {var timer = null; var anterior = nulo; function de return () {var now = +new Date (); if (! anterior) anterior = ahora; if (al menos && ahora - anterior> al menos) {fn (); // reinicie la última hora de inicio a la hora final de este tiempo anterior = ahora; ClearTimeOut (temporizador); } else {ClearTimeOut (temporizador); timer = setTimeOut (function () {fn (); anterior = null;}, demora); }}}}; Window.onscroll = Throttle (Testfn, 200); // window.onscroll = Throttle (testfn, 500, 1000); </script> </body> </html>Usamos dos casos para probar el efecto, a saber, agregando al menos activar al menos el al menos y no agregar:
// case 1window.onscroll = Throttle (testfn, 200); // case 2window.onscroll = Throttle (Testfn, 200, 500);
El caso 1 se manifiesta como: TestFn no se llamará durante el proceso de desplazamiento de la página (no se puede detener), y se llamará una vez hasta que se detenga, lo que significa que el último asentamiento en el acelerador se ejecuta, el efecto se muestra en la figura:
El caso 2 se manifiesta como: durante el proceso de desplazamiento de la página (no se puede detener), TestFn se retrasará en 500 ms por primera vez (de al menos la lógica de retraso) y luego ejecutará al menos cada 500 ms. El efecto es como se muestra en la figura
Como se muestra anteriormente, se han introducido los efectos que queremos lograr y se proporcionan ejemplos. Espero que sea útil para los amigos necesitados. Los lectores pueden pensar en algunas optimizaciones auxiliares posteriores por sí mismos, como: Funcionen este punto, el ahorro de valor de retorno, etc. De todos modos, ¡se siente genial entender este proceso con cuidado!