Primeiro, vamos entender o que é o acelerador
1. Definição
Se você apertar a torneira até que a água esteja fluindo na forma de gotículas de água, você descobrirá que de vez em quando, uma gota de água fluirá.
Ou seja, um ciclo de execução é definido com antecedência e quando a hora em que a ação é chamada é maior ou igual ao ciclo de execução, a ação é executada e, em seguida, o próximo novo ciclo é inserido.
Definição da interface:
* Quando o controle de frequência retorna, a função é chamada continuamente, a frequência de execução de ação é limitada a tempos/ atraso* @param atraso {número} Tempo de atraso, unidade milissegundos* @param ação {function} solicita a função de chamada e a função e a função que precisa ser chamada no aplicativo real* @return {function} retorna a função de cliente*2. Implementação simples
var acelerador = função (atraso, ação) {var last = 0return function () {var curr = +new date () if (curr - last> teltar) {action.apply (this, argumentos) last = curr}}}Deixe -me explicar essa função de aceleração cuidadosamente abaixo.
No evento DOM do navegador, alguns eventos serão acionados continuamente com as operações do usuário. Por exemplo: redimensione a janela do navegador, role a página do navegador e mousemove. Ou seja, quando o usuário acionar essas operações do navegador, se o método de manuseio de eventos correspondente estiver vinculado ao script, esse método será acionado continuamente.
Não é isso que queremos, porque às vezes se o método de manuseio de eventos for relativamente grande, operações DOM, como complexo e desencadear constantemente esses eventos, causarão perdas de desempenho, resultando em um declínio na experiência do usuário (resposta lenta da interface do usuário, navegador preso etc.). Portanto, geralmente adicionamos lógica ao evento correspondente para atrasar a execução.
De um modo geral, usamos o seguinte código para implementar esta função:
var count = 0; function testfn () {console.log (count ++); } // Quando o navegador redimensiona // 1. Limpe o temporizador anterior // 2. Adicione um cronômetro para atrasar a função real testfn por 100 milissegundos para acionar a janela.onResize = function () {var timer = null; ClearTimeout (timer); timer = setTimeout (function () {testfn ();}, 100);};Os alunos cuidadosos descobrirão que o código acima está realmente errado. Esse é um problema que os novatos farão: o valor de retorno da função Settimeout deve ser salvo em uma variável global relativa, caso contrário, um novo timer será gerado toda vez que o redimensionamento for redimensionado, o que não alcançará o efeito que enviará.
Então, modificamos o código:
var timer = null; window.onResize = function () {clearTimeout (timer); timer = setTimeout (function () {testfn ();}, 100);};No momento, o código é normal, mas há outro novo problema - um timer variável global é gerado. Isso é algo que não queremos ver. Se esta página tiver outras funções, ela também será chamada de timer. Códigos diferentes causarão conflitos antes. Para resolver esse problema, precisamos usar um recurso de idioma do JavaScript: fechamentos de fechamentos. Os leitores podem aprender sobre o conhecimento relacionado no MDN. O código modificado é o seguinte:
/*** Função Método de estrangulamento* @param Função FN Função de chamada de atraso* @Param Número Atraso quanto tempo dura o atraso* @return Função Método para atrasar a execução*/var acelerador = função (fn, atraso) {var timer = null; retornar function () {clearTimeout (timer); timer = setTimeout (function () {fn ();}, atraso); }}; window.onResize = acelerador (testfn, 200, 1000);Usamos uma função de fechamento (aceleração do acelerador) para colocar o cronômetro internamente e retornar a função de processamento de atraso. Dessa forma, a variável do timer é invisível para o exterior, mas a variável do timer também pode ser acessada quando a função de atraso interno é acionada.
Obviamente, este método de escrita não é fácil para os novatos entenderem. Podemos mudar o método de escrita para entender:
VAR acelerador = função (fn, atraso) {var timer = null; retornar function () {clearTimeout (timer); timer = setTimeout (function () {fn ();}, atraso); }}; var f = acelerador (testfn, 200); window.onResize = function () {f ();};Aqui está um ponto de vista: a função retornada pelo acelerador depois de ser chamada é a verdadeira função que precisa ser chamada quando o tamanho é acionado
Agora parece que esse método está próximo da perfeição, mas não é o caso em uso real. Por exemplo:
Se o usuário redimensionar constantemente o tamanho da janela do navegador, a função de processamento de atraso não será executada uma vez
Portanto, precisamos adicionar outra função: quando o usuário desencadear redimensionar, ele deve ser acionado pelo menos uma vez dentro de um determinado período de tempo. Como está dentro de um determinado período de tempo, essa condição de julgamento pode levar o tempo atual milissegundos, e cada chamada de função subtraia o tempo atual do último tempo de chamada e, em seguida, julga que, se a diferença for maior que um determinado período de tempo, será enviado diretamente, caso contrário, ele ainda seguirá a lógica de atraso do tempo limite.
O que precisa ser apontado no código a seguir é:
A função da variável anterior é semelhante à do timer. Ambos são os identificadores que registram a última vez e devem ser variáveis globais relativas
Se o processo lógico seguir a lógica "acionada pelo menos uma vez", a chamada de função precisará ser concluída para redefinir o anterior para o horário atual. Em suma, é realmente o atual em comparação com a próxima vez.
/*** Função Método de estrangula* Função @param Função de atraso Função* @param Número Atraso quanto tempo dura o atraso* @param número pelo menos quanto tempo ele é acionado* @return Função Método para retardar a execução*/var acelerador = função (fn, atraso, pelo menos) {var timer = null; var anterior = nulo; return function () {var agora = +new Date (); if (! anterior) anterior = agora; if (agora - anterior> pelo menos) {fn (); // Redefina o último horário de início até o horário final deste tempo anterior = agora; } else {clearTimeout (timer); timer = setTimeout (function () {fn ();}, atraso); }}};prática:
Simulamos uma cena de aceleração quando uma janela rola, ou seja, quando o usuário rola a página para baixo, precisamos reduzir alguns métodos, como: calcular a posição DOM etc., que requer operação contínua dos elementos DOM.
O código completo é o seguinte:
<! Doctype html> <html lang = "en"> <head> <meta charset = "utf-8"> <title> acelerador </title> </ad head> <body> <div style = "altura: 5000px"> <id id = "Demo" style = "rode: fixado;"> </div> document.getElementById ('Demo'); function testfn () {Demo.innerhtml += 'testfn foi chamado' +++ count +'time <br>';} var acelerador = função (fn, atraso, pelo menos) {var timer = null; var anterior = nulo; return function () {var agora = +new Date (); if (! anterior) anterior = agora; if (pelo menos && agora - anterior> pelo menos) {fn (); // Redefina o último horário de início até o horário final deste tempo anterior = agora; ClearTimeout (timer); } else {clearTimeout (timer); timer = setTimeout (function () {fn (); anterior = null;}, atraso); }}}}; window.onscroll = acelerador (testfn, 200); // window.onscroll = acelerador (testfn, 500, 1000); </script> </body> </html>Utilizamos dois casos para testar o efeito, a saber, adicionando pelo menos o desencadeando pelo menos o pelo menos e não adicionando:
// case 1window.onscroll = acelerador (testfn, 200); // case 2window.onscroll = acelerador (testfn, 200, 500);
O caso 1 se manifesta como: O TESTFN não será chamado durante o processo de rolagem da página (não pode ser interrompido) e será chamado uma vez até que pare, o que significa que o último Settimeout no acelerador é executado, o efeito é como mostrado na figura:
O caso 2 se manifesta como: Durante o processo de rolagem da página (não pode ser interrompido), o TESTFN será atrasado em 500ms pela primeira vez (a partir de pelo menos a lógica de atraso) e, em seguida, executará pelo menos a cada 500ms. O efeito é como mostrado na figura
Como mostrado acima, os efeitos que queremos alcançar foram introduzidos e os exemplos são fornecidos. Espero que seja útil para os amigos necessitados. Os leitores podem pensar em algumas otimizações auxiliares subsequentes por si mesmas, como: FUNCIONAR ESTE PONTRO, REVURTO VALOR ECT ETC. De qualquer forma, é ótimo entender esse processo com cuidado!