JS事件中防抖debounce和节流throttle以及requestAnimationFrame

浏览器的一些事件,如:resize,scroll,keydown,keyup,keypress,mousemove等。这些事件触发频率太过频繁,绑定在这些事件上的回调函数会不停的被调用。这样浏览器的目的是为了保证信息的一致性,而对于我们来说就是一种资源的浪费了。
debounce的作用是在让在用户动作停止后延迟x ms再执行回调。
throttle的作用是在用户动作时没隔一定时间(如200ms)执行一次回调。
他们两个的共同点就是将多次回调的触发合并成一次执行。这就大大避免了过于频繁的事件回调操作。
本质就是将事件回调函数用debounce或throttle包装,事件触发的频率没有改变,只是我们自定义的回调函数的执行频率变低了。这个处理是基于DOM操作是十分巨大的开销。所以如果你的回调函数只是处理一些js的数据,那么用不用防抖和节流处理是一样的。

debounce实现

function debounce(fn,delay){

    var delay=delay||200;
    var timer;
    return function(){
        var th=this;
        var args=arguments;
        if (timer) {
            clearTimeout(timer);
        }
        timer=setTimeout(function () {
                timer=null;
                fn.apply(th,args);
        }, delay);
    };
}
例子1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<style type="text/css">
    #dom{
        width: 200px; height: 200px; background: red
    }
</style>
<body>
    <div id="dom"></div>
</body>
<script type="text/javascript">
document.getElementById('dom').addEventListener("mousemove",debounce(function(){
    console.log(this)
}));
</script>
</html>
例子2
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div class="keycont">
        输入:<input type="text" id="keybtn"/>
    </div>
    <div style="position:relative">
        <div class="keysend" id="keyinfo"></div>
    </div>
</body>
<script type="text/javascript">
    var info=document.getElementById("keyinfo");
    var btn=document.getElementById("keybtn");
    btn.addEventListener("keydown",debounce(function(){
        var div=document.createElement("div");
        var str=new Date();
        div.innerText=str
        info.appendChild(div);
    },500));
</script>
</html>

throttle实现

function throttle(fn,interval){
    var last;
    var timer;
    var interval=interval||200;
    return function(){
        var th=this;
        var args=arguments;
        var now=+new Date();
        if(last&&now-last<interval){
            clearTimeout(timer);
            timer=setTimeout(function(){
                last=now;
                fn.apply(th,args);
            },interval);
        }else{
            last=now;
            fn.apply(th,args);
        }
    }
}
window.addEventListener('scroll', throttle(function  () {
   console.log(11111) 
}));

使用方法跟debounce一样。代码逻辑也类似。在触发时超过间隔时间interval ms则执行。否则不执行。if判断中的setTimeout是保证最后一次事件触发后能够调用,所以每次执行没到间隔时间时先清除timer,再重新启动timer。而在达到间隔时间时执行函数。代码逻辑也很简单,不用多说,相信聪明的你一看就能明白。

这个throttle节流的功能就是在固定的间隔时间执行回调函数,最常用的用处就是resize,scroll事件中处理。

requestAnimationFrame

上面介绍的抖动与节流实现的方式都是借助了定时器 setTimeout ,但是如果页面只需要兼容高版本浏览器或应用在移动端,又或者页面需要追求高精度的效果,那么可以使用浏览器的原生方法 requestAnimationFrame
window.requestAnimationFrame() 这个方法是用来在页面重绘之前,通知浏览器调用一个指定的函数。这个方法接受一个函数为参,该函数会在重绘前调用。常用于 web 动画的制作,用于准确控制页面的帧刷新渲染,让动画效果更加流畅,当然它的作用不仅仅局限于动画制作,我们可以利用它的特性将它视为一个定时器。(当然它不是定时器)

通常来说,requestAnimationFrame 被调用的频率是每秒 60 次,也就是 1000/60 ,触发频率大概是 16.7ms 。(当执行复杂操作时,当它发现无法维持 60fps 的频率时,它会把频率降低到 30fps 来保持帧数的稳定。)

简单而言,使用 requestAnimationFrame 来触发滚动事件,相当于上面的:

throttle(fn,16.7)

总结

debounce用在keydown事件上验证用户名最好。而throttle用在resize改变布局上,onscroll滚动时候的。 requestAnimationFrame 可调节性十分差。但是相比 throttle(func, 16.7) ,用于更复杂的场景时,requestAnimationFrame 可能效果更佳,性能更好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue和Loadsh在前端开发非常常用,在前端开发过程常常遇到需要防抖节流的情况。下面我们将具体介绍Vue和Loadsh对事件防抖节流的实现。 事件防抖是指在短时间内多次触发同一事件,只执行最后一次触发的事件。这种现象常见于浏览器不断地触发resize、scroll、mousemove等多种事件。为了避免短时间内多次执行同一事件而导致的浪费资源和卡顿现象,我们通常会采用事件防抖的方式来避免这种情况的出现。 Vue通过@keyup、@keydown、@input等事件绑定方式可以实现事件防抖。例如: <template> <div> <input type="text" v-model="value" @keyup="debounceHandle"/> <div>{{ value }}</div> </div> </template> <script> import debounce from 'loadash/debounce'; export default { data () { return { value: '' } }, methods: { debounceHandle: debounce(function() { console.log('事件防抖'); }, 500) } } </script> 上述代码,我们使用loadash/debounce函数,这个函数会返回一个debounced函数。在此处,我们将debounced函数绑定到@keyup事件上,设置延迟时间为500毫秒。这样在输入框输入的时候,每次输入之后都会等待500毫秒后执行该函数,确保不会多次执行该函数。 事件节流是指在一段时间内,多次触发同一事件,但只执行一次函数。相比于事件防抖事件节流把触发的事件按照一定规律分为多个时间段,在一个时间段内只执行一次函数。 Vue和Loadsh的throttle函数可以实现事件节流。例如: <template> <div> <input type="text" v-model="value" @keyup="throttleHandle"/> <div>{{ value }}</div> </div> </template> <script> import throttle from 'loadash/throttle'; export default { data () { return { value: '' } }, methods: { throttleHandle: throttle(function() { console.log('事件节流'); }, 500) } } </script> 上述代码,我们使用loadash/throttle函数,这个函数会返回一个throttled函数。在此处,我们将throttled函数绑定到@keyup事件上,设置间隔时间为500毫秒。这样在输入框输入的时候,在500毫秒时间内只执行一次函数。 综上所述,事件防抖事件节流是前端开发非常常用的技术,通过Vue和Loadsh的配合可以轻松实现事件防抖事件节流。在实际开发过程,需要根据具体情况选择使用防抖节流技术。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值