[] Seguimiento subrayado estabilización de imagen escuela JavaScript

prefacio

Algunos activación de un evento encontrado con frecuencia en el desarrollo de front-end, tales como:

  • 的 ventana de cambio de tamaño, desplazamiento
  • mousedown, mousemove
  • keyup, keydown
  • ......

Con este fin, damos un código de ejemplo para ver con qué frecuencia el evento de disparo:

Escribimos index.htmlel archivo:

<!DOCTYPE html>
<html lang="zh-cmn-Hans">

<head>
    <meta charset="utf-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge, chrome=1">
    <title>debounce</title>
    <style>
        #container{
            width: 100%; height: 200px; line-height: 200px; text-align: center; color: #fff; background-color: #444; font-size: 30px;
        }
    </style>
</head>

<body>
    <div id="container"></div>
    <script src="debounce.js"></script>
</body>

</html>

debounce.js archivo de código de la siguiente manera:

var count = 1;
var container = document.getElementById('container');

function getUserAction() {
    container.innerHTML = count++;
};

container.onmousemove = getUserAction;

Echemos un vistazo a los resultados:
Aquí Insertar imagen Descripción
de izquierda a derecha de la diapositiva disparado 165 veces la función getUserAction!

Debido a que este ejemplo es muy simple, por lo que el navegador reaccionó completamente terminado, pero si es complejo o devolución de llamada Ajax solicitud de ella? Supongamos que uno segundo disparador 60 veces, cada una devolución de llamada se completará dentro de 1000/60 = 16.67ms, de lo contrario habrá aparece Caton.

Para resolver este problema, existen dos soluciones:

  • estabilización de imagen de supresión de rebotes
  • acelerador del acelerador

Agitar

Hoy hablaremos de una realización de estabilización de imagen.

principio de estabilización de imagen es la siguiente: a pesar de que de disparador, pero debe llevar a cabo sólo después de que el evento de disparo n segundos, si se dispara un evento dentro de n segundos ha dado lugar a este evento, entonces voy a tomar tiempo para que prevalecerá el nuevo evento , n segundos después de la ejecución, en definitiva, es esperar a que termine evento de disparo eventos de activación ya no está dentro de n segundos, he realizado muy testarudo na!

Primera edición> directamente al grano

De acuerdo con esta expresión, podemos escribir la primera versión del código:

// 第一版
function debounce(func, wait) {
    var timeout;
    return function () {
        clearTimeout(timeout)
        timeout = setTimeout(func, wait);
    }
}

Si queremos utilizarlo para los mejores ejemplos de un principio de un ejemplo:

container.onmousemove = debounce(getUserAction, 1000);

Ahora cómo moverse con usted, ya que se haya completado la mudanza no hay factores desencadenantes más largos dentro de 1000 ms, que no se ha ejecutado el evento. Buscar en el uso efecto:
Aquí Insertar imagen Descripción
de repente reducido de 165 1 se convirtió en Bang Bang da, entonces mejoramos !.

Segunda Edición> esto significa que existe un problema

Si nos CONSOLE.LOG (este), cuando no se utiliza la función de supresión de rebotes, este valor en función de getUserAction:

<div id="container"></div>

Pero si utiliza nuestra función anti-rebote, esto apuntará al objeto de ventana!

Así que tenemos este punto al objeto correcto.

Modificamos el código bajo:

// 第二版
function debounce(func, wait) {
    var timeout;

    return function () {
        var context = this;

        clearTimeout(timeout)
        timeout = setTimeout(function(){
            func.apply(context)
        }, wait);
    }
}

Ahora esto se ha señalado correctamente. Echemos un vistazo a un problema -

Tercera Edición> objetos de eventos

Manejo en JavaScript del evento será el evento objeto de evento, que revisar a la baja la función getUserAction:

function getUserAction(e) {
    console.log(e);
    container.innerHTML = count++;
};

Si no usamos la función debouce aquí se imprimirá objeto MouseEvent, como se muestra:
Aquí Insertar imagen Descripción
pero la función de supresión de rebotes en nuestra aplicación, pero sólo se imprimirá sin definir!

Así hemos modificado el código de abajo:

// 第三版
function debounce(func, wait) {
    var timeout;

    return function () {
        var context = this;
        var args = arguments;

        clearTimeout(timeout)
        timeout = setTimeout(function(){
            func.apply(context, args)
        }, wait);
    }
}

En este punto es la impresión de lo que el valor de e cuando se utiliza la función de supresión de rebotes ya no está definido arriba!

Hasta ahora, nos fijamos dos problemas menores:

  1. este punto
  2. objetos de eventos

Cuarta Edición> ejecutado inmediatamente

Esta vez, el código ha sido muy perfecto, pero con el fin de realizar esta función más perfecta, vamos a pensar en una nueva demanda.

Esta demanda es:

No quiero tener que esperar hasta que los acontecimientos desencadenan la ejecución de parada, quiero ejecutar inmediatamente la función, y luego esperar hasta que el tope se activa después de n segundos antes de que puedan volver a activar la ejecución.

Piense de esta demanda es también algo muy razonable, que si añadimos un juicio argumento inmediata se ejecuta inmediatamente.

// 第四版
function debounce(func, wait, immediate) {

    var timeout;

    return function () {
        var context = this;
        var args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timeout;
            timeout = setTimeout(function(){
                timeout = null;
            }, wait)
            if (callNow) func.apply(context, args)
        }
        else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
    }
}

Otra mirada a los efectos de:
Aquí Insertar imagen Descripción

Quinta Edición> valor de retorno

En este punto, nota que hay getUserAction función puede devolver un valor, por lo que tenemos que volver resultado de la ejecución de la función, pero cuando regreso inmediato es falsa, ya que el uso de setTimeout, lo haremos func.apply (contexto, args) valor a la variable, y finalmente devolver el valor de tiempo siempre será indefinido, así que sólo devolverá el resultado ejecución de la función es cierto cuando la inmediata.

// 第五版
function debounce(func, wait, immediate) {

    var timeout, result;

    return function () {
        var context = this;
        var args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timeout;
            timeout = setTimeout(function(){
                timeout = null;
            }, wait)
            if (callNow) result = func.apply(context, args)
        }
        else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
        return result;
    }
}

Sexta Edición> Cancelado

Por último, vamos a pensar un poco la demanda, quiero cancelar la función de supresión de rebotes, por ejemplo, me intervalo de tiempo de supresión de rebotes es de 10 segundos, inmediata es cierto, este es el caso, y por lo que tengo sólo después de 10 segundos hasta el evento de re-disparo, y ahora quiere tener una botón, al hacer clic, cancelar la estabilización de la imagen, así que fui al gatillo, y se puede ejecutar de inmediato, no es muy feliz?

Por esta demanda, se escribe la versión final del código:

// 第六版
function debounce(func, wait, immediate) {

    var timeout, result;

    var debounced = function () {
        var context = this;
        var args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timeout;
            timeout = setTimeout(function(){
                timeout = null;
            }, wait)
            if (callNow) result = func.apply(context, args)
        }
        else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
        return result;
    };

    debounced.cancel = function() {
        clearTimeout(timeout);
        timeout = null;
    };

    return debounced;
}

Entonces, ¿cómo utilizar esta función se cancela? Aún demostración anterior es un ejemplo:

var count = 1;
var container = document.getElementById('container');

function getUserAction(e) {
    container.innerHTML = count++;
};

var setUseAction = debounce(getUserAction, 10000, true);

container.onmousemove = setUseAction;

document.getElementById("button").addEventListener('click', function(){
    setUseAction.cancel();
})

Efecto de demostración es la siguiente:
Aquí Insertar imagen Descripción

Ahora que hemos logrado una completa subrayado la función de supresión de rebotes, felicitaciones, Sahua!

la versión simple de estabilización de imagen (auto-complementaria)

Centrarse en el uso de esta modificación y argumentos se aplican

function debounce(fnc,wait){
    var timer = null;  // 创建一个标记用来存放定时器的返回值
    return function(){
        clearTimeout(timer); // 每当用户输入的时候把前一个 setTimeout clear 掉
        timer = setTimeout(function(){ // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 wait 时间内如果还有字符输入的话,就不会执行 fnc 函数
            fnc.apply(this,arguments);
        },wait);
    }
}

function sayHi(){
    console.log('防抖')
}

var inp = document.getElementById('box');
inp.addEventListener('input',debounce(sayHi,500))

Estabilización del acelerador escenario de aplicación (auto-complementaria)

Sobre los escenarios de estabilización de imagen de referencia del acelerador
Aquí Insertar imagen Descripción

epílogo

sobre ~

Salto del acelerador enlace ↓

Mengchuo sigue subrayado la escuela del acelerador

Publicados 134 artículos originales · ganado elogios 80 · Vistas a 30000 +

Supongo que te gusta

Origin blog.csdn.net/Umbrella_Um/article/details/100884955
Recomendado
Clasificación