最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 防抖函数三个版本--层层递进

    正文概述 掘金(Mugen310)   2021-04-05   497

    一.防抖函数的理解--层层递进

    防抖和节流原理这里不会细述,主要是讲如何从一个最简单的防抖函数一直优化到比较完美的状态。(最终版比现在网上blog的要稍微好一点)

    ?当然也提供一个原理链接,同样也是我最初的参考防抖和节流

    ▼对于防抖和节流我的理解是:防抖是停下来了才开始执行, 节流是固定时间不管发生多少次时间都执行固定次数

    先给一个最基础版的防抖(非立即执行)

    HTML:

    <div id="content"
         style="height:150px;
         line-height:150px;
         text-align:center;
         color: #fff;
         background-color:lightseagreen;
         font-size:80px;">
        0
    </div>
    

    1.基础版

    js:

    let easyDebounce=(func,wait)=>{
        let timeout;
        return function (){
            clearTimeout(timeout);
            timeout=setTimeout(()=>{
                func();
            },wait)
        }
    }
    
    let item=document.querySelector("#content");
    let num=0;
    function count() {
        item.innerHTML = String(++num);
    }
    item.addEventListener('mousemove',easyDebounce(count,1000));
    

    ▼效果为不管在div内移动多少次, 只会触发最后一次的func

    防抖函数三个版本--层层递进

    可以看出来我们已经实现了基本的防抖了。不过这里有两个缺陷

    1. 我们直接调用func(), 这样的话就没法给回调函数count进行传参, 连默认的event都传不进来, 因为event参数是绑定在匿名函数上的!!!
    2. 我们在定时器中的回调函数的this指向的是顶层对象window, 但是原本应该是item!!!

    (废话几句, 大佬可以跳过???: 因为这里会将返回的函数绑定在item上, 其完整写法是 EventTarget.addEventListener(). 再多说一点easyDebounce执行的时候其中的this指向window, 因为绑定在item上的函数不是easyBounce而是esayBounce返回的函数...) 具体执行是这样的:

    let easyDebounce=(func,wait)=>{
        let timeout;
        console.log(this)            //▼window
        return function (){
            console.log(this);         //▼item
            clearTimeout(timeout);
            timeout=setTimeout(()=>{
                func();                
            },wait)
        }
    }
    
    let item=document.querySelector("#content");
    let num=0;
    function count() {
        item.innerHTML = String(++num);
        console.log(this);             //▼window
    }
    

    那么如何改进呢?

    2.标准防抖

    let easyDebounce=(func,wait)=>{
        let timeout;
        return function (){
            let context=this;
            let args=arguments;
            clearTimeout(timeout);
    
            timeout=setTimeout(()=>{
                func.apply(context,args);
            },wait)
        }
    }
    
    let item=document.querySelector("#content");
    let num=0;
    function count(event) {
        console.log(this);      //item
        console.log(event);     //MouseEvent
        item.innerHTML = String(++num);
    }
    item.addEventListener('mousemove',easyDebounce(count,1000));
    

    ?此时我们通过apply方法, 成功解决了this和传参的问题!!! 这也是比较流行的一种写法

    可是如果我们想要给回调函数count传参该怎么办呢?

    item.addEventListener('mousemove',easyDebounce(count(param),1000));
    

    ❌这样肯定是不行的啦, 回调函数是传地址, 让别人去调用, 这么写会立即调用count

    这就要用到下面的方法了------通过外部函数传参

    3.防抖Plus

    let debounce=function (func,wait){
        let timeout;
        let externalArgs=[...arguments].slice(2);
        return function () {
            let context=this;
            let args=externalArgs.concat([...arguments]);
            if (timeout) clearTimeout(timeout);
            timeout=setTimeout(()=>{
                func.apply(context,args);
            },wait)
        }
    }
    function count() {
        console.log(this);
        console.log(arguments);  //Arguments(2)['externalArgs',MouseEvent]
        item.innerHTML = String(num++);
    }
    item.addEventListener('mousemove',debounce(count,1000,'externalArgs'));
    

    我们可以在debounce中传参, 并利用arguments在count使用参数

    防抖函数三个版本--层层递进

    感谢您的阅读!!! 初学前端小白, 如有不对, 请不吝赐教!!!


    起源地下载网 » 防抖函数三个版本--层层递进

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元