美文网首页
防抖和节流

防抖和节流

作者: kugua666 | 来源:发表于2020-08-18 21:23 被阅读0次

    1、防抖

    指触发事件后在n秒后函数执行,如果在n秒内又触发了事件,则会重新计算函数执行时间。应用场景(适合多次事件只响应一次的情况):给按钮加防抖函数防止表单多次提交;判断scroll是否滑到底部;对于输入框连续输入进行AJAX验证时,用函数防抖能有效减少请求次数。

    现给一个场景:现监听一个输入框,文字变化后触发change事件。若直接用keyup事件,则会频繁触发change事件。加了防抖后,用户输入结束或暂停时,才会触发change事件。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <input type="text" id="input1">
    </body>
    <script>
        const input1 = document.getElementById('input1')
    //1、不加防抖 ,会一直触发change事件
        input1.addEventListener('keyup', function(){
                console.log(input1.value)
        })
    
    //2、简单实现防抖
        let timer = null
        input1.addEventListener('keyup', function(){
            if(timer){
                clearTimeout(timer)
            }
            timer = setTimeout(() => {
                //模拟触发change事件
                console.log(input1.value)
                //清空定时器
                timer = null
            }, 1000)
        })
    
    //3、将防抖函数这个工具进行封装
        function debounce(fn, delay = 50){
            //timer是闭包中的,不能被别人修改
            let timer = null
            return function(){
                if(timer){
                    clearTimeout(timer)
                }
                timer = setTimeout(() => {
                    fn.apply(this, arguments)
                    timer = null
                }, delay)
            }
        }
        input1.addEventListener('keyup', debounce(function(){ 
            console.log(input1.value)
        }, 600))
    </script>
    </html>
    

    则封装后的防抖函数为:

        function debounce(fn, delay = 50){
            let timer = null  //timer是闭包中的,不能被别人修改
            return function(){
                if(timer){
                    clearTimeout(timer)
                }
                timer = setTimeout(() => {
                    fn.apply(this, arguments)
                    timer = null
                }, delay)
            }
        }
    

    2、节流

    连续发送的事件在n秒内只执行一次函数。应用场景(适合大量事件按时间做平均分配触发):DOM元素拖拽;Canvas画笔功能。

    现给一个场景:拖拽一个元素,要随时拿到该元素被拖拽的位置。若直接用drag事件,则会频繁触发,很容易导致卡顿。加了节流后,无论拖拽速度多快,都会每隔固定时间触发一次。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            #div1{
                border: 1px solid #ccc;
                width: 200px;
                height: 100px;
            }
        </style>
    </head>
    <body>
        <div id = "div1" draggable="true">可拖拽</div>
        <script>
            const div1 = document.getElementById('div1')
      
      //1、简单实现节流
            let timer = null
            div1.addEventListener('drag', function(e){
                if(timer){
                    return
                }
                timer = setTimeout(() => {
                    console.log(e.offsetX, e.offsetY)
                    timer = null //定时器执行了,才让timer为空
                }, 1000)            
            })
    
      //2、将节流函数这个工具进行封装
            function throttle(fn, delay = 100){
                let timer = null
                return function(){ 
                    if(timer){
                        return
                    }
                    timer = setTimeout(() => {
                        fn.apply(this, arguments)
                        timer = null
                    },delay)
                }
            }
            div1.addEventListener('drag', throttle(function(e){ //形参e会传给throttle函数运行后返回的函数
                    console.log(e.offsetX, e.offsetY)   
            },200))
        </script>
    </body>
    </html>
    

    则封装后的节流函数为:

            function throttle(fn, delay = 100){
                let timer = null
                return function(){ 
                    if(timer){
                        return
                    }
                    timer = setTimeout(() => {
                        fn.apply(this, arguments)
                        timer = null
                    },delay)
                }
            }
    

    相关文章

      网友评论

          本文标题:防抖和节流

          本文链接:https://www.haomeiwen.com/subject/qbzkjktx.html