防抖和节流

窗口的resize、scroll、输入框内容校验等操作时,如果这些操作处理函数是较为复杂或页面频繁重渲染等操作时,在这种情况下如果事件触发的频率无限制,会加重浏览器的负担,导致用户体验非常糟糕。此时我们可以采用debounce(防抖)和throttle(节流)的方式来减少触发的频率,同时又不影响实际效果。

防抖

在事件被触发n秒之后执行,如果在此期间再次触发事件,则重新开始计时。

我们模拟输入表单数据,自动获取后台数据,联想搜索,反馈回前台。监听keyup事件,如果每次输入一个字符,就发送一次请求,那么将在极短的时间发送非常多次请求,后台服务器不堪重负!

// 监听input值 模糊搜索 防止一直搜索

// 需要触发的函数
function debounce(d){
    console.log("联想搜索phoneNumber:" + d)
}
let inp = document.querySelector("#phone");
// 输入触发的事件
function getPhone(fn,delay){
    let timer;
    // 使用闭包,保证每次使用的定时器是同一个
    return (d)=>{
        clearTimeout(timer);
        timer = setTimeout(()=>{
            fn(d);
            // 结束之后清除定时器
            clearTimeout(timer);
        },delay)
    }
}

let getPhoneDebounce = getPhone(debounce,1000);

inp.addEventListener('keyup',(e)=>{
    getPhoneDebounce(e.target.value);
})

立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。
/**
 * @param func 函数
 * @param wait 延迟执行毫秒数
 * @param immediate true 表立即执行,false 表非立即执行
 */
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);
        }
    }
}

节流

如果持续触发一个事件,则在一定的时间内只执行一次事件。

我们模拟射击,首先第一次点击射击的时候,打出一发子弹,当以极短的时间再次点击射击的时候,由于需要‘冷却’——也就是节流,再次点击无效,当冷却时间过了之后,再次点击射击,则继续下一次射击
准备工具:一个射击的函数shot, 一个判断射击间隔是否结束的函数nextShot,一个触发射击的按钮,判断射击是否结束的定时器timer
基本思路:第一次点击按钮的时候,触发shot,当继续点击的时候,射击无效,只有过了定时器设置的时间才可以继续射击。

// 模拟射击
function shot(){
    console.log('射击')
}
let btn = document.querySelector('#shot');
function nextShot(fn,delay){
    let timer;
    // 闭包原理同上
    return ()=>{
        // 定时器存在,无法射击
        if(timer){
            console.log('禁止射击');
        }else{  // 定时器不存在,射击,并设置定时器
            fn();
            timer = setTimeout(()=>{
                // 定时器结束,可以射击
                clearTimeout(timer);
                timer = null;
            },delay)
        }
    }
}
let start = nextShot(shot,20);
btn.addEventListener('click',()=>{
    start();
})

参考文章来源:

你可能感兴趣的:(javascript,前端,vue.js,node.js,es6)