博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
你们都会的防抖与节流
阅读量:5996 次
发布时间:2019-06-20

本文共 3896 字,大约阅读时间需要 12 分钟。

这一篇文章我想写一下防抖与节流,因为我自己不是很理解而且说实话,以前知道,但是老忘,虽然概念还有一些简单的写法会,但还是缺乏练习和深刻的理解。

当我们不加防抖或节流的时候就像这样,鼠标滑过触发这么多次,所以我们一个使用防抖或节流来限制它的请求次数而不是触发次数。关于防抖与节流的应用和解释自行查找资料。

function fn(e) { console.log(this); console.log(e); app.innerHTML = num ++;}

1.防抖

  • 简单实现
function debounce(fn, delay) {    let timer = null;    return function(){        clearTimeout(timer);        timer = setTimeout(function () {            fn();        }, delay);    }}

使用节流后

app.onmousemove = fdebounce(fn, 1000);

我们发现次数减少了太多,因为只要你在delay时间内不停地触发就不会执行直到你的间隔时间大于delay才会执行。

我们来看一下this和event。

this是window,event是undefined。

  • 修复this指向和事件参数
function debounce(fn, delay) {    let timer = null,        that;    return function(e){        that = this;        clearTimeout(timer);        timer = setTimeout(function () {  //this指向window(非严格模式)            fn.apply(that, [e]);        }, delay);    }}

或者是

function debounce(fn, delay) {    let timer = null;    return function(e){        clearTimeout(timer);        timer = setTimeout(()=>{ //箭头函数            fn.apply(this, [e]);        }, delay);    }}

  • 增强版(是否立即执行)
function debounce(fn, delay, immediate) {    let timer = null,        that;     return function (e) {        that = this;        clearTimeout(timer);        if(immediate){  //是否立即执行            if(!timer){  // 如果没有设置定时器就先执行                fn.apply(that, [e]);            }            timer = setTimeout(function () {                 timer = null;// 设置定时器,使其在delay毫秒内不能执行,过了delay毫秒后在执行            }, delay);        }else{ //否则延时执行            timer = setTimeout(function () {                fn.apply(that, [e])            }, delay);        }    };}//这个if...else只能执行一个,要不先执行,要不延时执行

一开始会执行一次,因为录制不能显示鼠标所以理解一下。

  1. 节流
  • 简易版(时间戳)
function throttle(fn, delay) {    let last = 0, //上次执行时间        now; //执行时的时间    return function (e) {        now = Date.now(); //当前时间        if(now - last >= delay){  //如果两次时间间隔大于delay,就执行            last = now; //重新赋值            fn();         }    };}

在规定时间delay毫秒内总会执行一次事件。

  • setTimeout版本(修复this指向和事件参数)
function throttle(fn, delay) {    let that,        timer = null;    return function (e) {        that = this;        if(!timer){  //如果没设置定时器就执行            timer = setTimeout(function () {                fn.apply(that, [e]);                timer = null; //果delay毫秒就设置timer,这样就能delay执行一次            }, delay);        }    };}
  • 修复this指向和事件参数(时间戳)
function throttle(fn, delay) {    let last = 0, //上次执行时间        now; //执行时的时间    return function (e) {        now = Date.now(); //当前时间        if(now - last >= delay){  //如果两次时间间隔大于delay,就执行            last = now; //重新赋值            fn.apply(this, [e]);         }    };}
  • 区别

    • 时间戳版本的会先执行
    • setTimeout版本的会后执行

所以可以结合一下他们两个。

  • 结合版
function throttle(fn, delay) {    let last = 0,  //上次执行时间        now, //当前时间        leftTime, //剩余时间        that,         timer = null;    return function (e) {        that = this;        now = Date.now();        leftTime = delay - (now - last);         if(leftTime <= 0){ //保证一开始就执行(先执行)            last = now;            fn.apply(that, [e]);        }else{            timer = setTimeout(function() {  //延时执行                fn.apply(that, [e]);                timer = null;            },delay)        }    };}

这样做总体思路没错,但是第一次会执行以后就是两个一起执行,因为条件都满足。

  • 修改
function throttle(fn, delay) {    let last = 0,        now,        leftTime,        that,        timer = null;    return function (e) {        that = this;        now = Date.now();        leftTime = delay - (now - last);        if(leftTime <= 0){            if(timer){ //如果有定时器就清除                clearTimeout(timer);                timer = null;            }            last = now;            fn.apply(that, [e]);        }else if(!timer){            timer = setTimeout(function() {                last = now; //如果时间满足就让他不满足                //总之除了第一次就只让其中一个执行                fn.apply(that, [e]);                timer = null;            },delay)        }    };}

一开始执行一次(时间戳),最后停止在执行一次(setTimeOut)。

转载地址:http://agqlx.baihongyu.com/

你可能感兴趣的文章
【转载】COM小结
查看>>
[android] AndroidManifest.xml - 【 manifest -> permission】
查看>>
20150728月度会议
查看>>
explain mysql性能优化
查看>>
NoSql---MongoDB基本操作
查看>>
【移动开发】WIFI热点通信(二)
查看>>
C#多线程编程实例 螺纹与窗口交互
查看>>
ByteBuffer用法小结
查看>>
使用linux mysql客户端建立表时遇到格式解析的问题
查看>>
find the mincost route(最小环,最短路,floyd)
查看>>
TCP 的那些事儿(上)
查看>>
Discuz!NT3.6与网站整合(操作用户信息)解决方案
查看>>
【今日推荐】10大流行的 Metro UI 风格的 Bootstrap 主题和模板
查看>>
Swift - 实现拨打电话
查看>>
在线代码编辑、保存与运行网址推荐
查看>>
博客园添加访问人数统计
查看>>
Yii2 RBAC 用到的表
查看>>
在使用DBMS_LOB.WRITEAPPEND()追加Clob内容的时候,报数字或值异常
查看>>
hibernate 在做更新和删除的时候一定要把事务开启
查看>>
将已有jar添加至本地maven仓库
查看>>