防抖和节流----一看就懂(附赠代码测试)

防抖和节流----一看就懂 (附赠代码测试)

1. 防抖

概念:多次触发一个动作,只执行最后一个动作


应用:页面滚动触发事件、窗口缩放事件、多次点击按钮事件等等


测试代码:例如一个页面很长,你要监听鼠标滚轮的滚动事件,但是又希望鼠标滚轮事件结束之后再进行操作时,请参考下面的简单例子

<!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>
/* 这里是样式 */
<style>
    .container{
        height: 2000px;
        width: 600px;
        margin: 0 auto;
        background-color: gray;
    }
</style>
<body>
	/*这里是模拟的盒子*/
    <div class="container"></div>
    <script>
        // 防抖
        function debounce(fn, wait) { 
        //传入两个参数,
        //参数 1 (fn)表示的是一个要执行的函数 ; 
        //参数 2 (wait)表示的是要等待的时间
            var timeout = null;
            //先定义一个标记,这个标记设置为 null
            return function () { 
            //然后返回一个函数 
                if (timeout !== null) clearTimeout(timeout);
                // 对这个标记进行判断 
                //如果这个标记不是空的情况下就执行后边的代码,
                //但是很明显初始化的时候标记是空的,所以第一次是不执行的,
                //直接走后边的步骤,定义这个变量为一个延迟函数,
                //这个时候这个 timer 就会在规定的时间内等待执行,
                //在规定时间内这个变量就是有意义的,所以再去操作这个函数的时候,
                //就符合 if 判断了,这个时候就会清除这个延迟函数,
                //这个延迟函数就不会执行,清除之后又重新加载一个延迟的函数,
                //这样,每一次操作,总是在一定的时间之内清除上一个函数,
                //然后开始一个新的延迟函数,就实现了在规定的时间之内反复的操作,
                //只会执行最后一次操作的目的,这个就是防抖
                timeout = setTimeout(fn, wait);
            }
        }
        // 处理函数 这里是模拟需要执行的函数,譬如你需要的 ajax 网络请求;
        // 这里就用一个简单的输出来表达
        function handle() {
            console.log(Math.random());
        }
        // 滚动事件
        // 这里添加一个window 下的事件监听,后边放上这个防抖的函数,
        // 防抖函数里边放上需要进行 防抖处理的函数和防抖的时间限制
        window.addEventListener('scroll', debounce(handle, 1000));
    </script>
</body>
</html>

恭喜你,成功看明白了~ 防抖 ~!

2. 节流

概念:在高频触发的操作下,稀释触发的频率;譬如本来要触发 100次/秒,现在减少到 1 次/秒

应用:页面滚动触发事件、窗口缩放事件、多次点击按钮事件等等

测试代码:例如一个页面要改变窗口尺寸,你要监听这个事件,但是又希望这个操作不要太频繁,请参考下面的简单例子

<!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>
<style>
    .container {
        height: 2000px;
        width: 600px;
        margin: 0 auto;
        background-color: gray;
    }
</style>

<body>
    <div class="container"></div>
    <script>
        // 首先我们要实现的效果是:在高频触发的操作下,稀释触发的频率,
        // 譬如本来要触发 100次/秒,现在减少到 1 次/秒
        function throttle(fn) {
            // 这里是声明一个实现节流的函数,这个函数里边需要传递一个我们要节流的目标函数 fn
            let canRun = true;
            // 这里声明一个参数 canRun 变成 true
            // 但是需要注意的是,并不是每一次事件都会触发这一个步骤
            // 这一个步骤只会执行一次,但是 return 的函数会执行很多次
            // 这个很类似于 react 框架中的高阶组件, 接受一个组件作为参数,然后返回一个组件,实际上运行的是返回的组件
            return function () {
                // 这里返回一个函数并执行
                if (!canRun) return;
                // 这里在要返回函数的内部做一个判断 如果这个 canRun 是 false 的话,直接结束这个函数不进行操作
                canRun = false;
                // 这里将 canRun 变成 false,变成 false 之后,继续执行后边的操作
                // 后边每隔一一秒钟才会执行被节流的函数 fn,
                // 并同时将 canRun 的值改成 true,成为 true 之后才能够再次执行fn,否则就直接结束
                setTimeout(() => {
                    fn.apply(this,arguments);
                    // 问:这里 fn 为什么需要传递 this 对象,以及 arguments 参数?
                    // 思路:如果打印的话,this--->window; argument--->event
                    // 答:
                    // 1. 传递 this 对象是 apply 的固定用法,即,apply 的第一个参数是要传递的对象
                    // 2. 传递 arguments 是因为,我们下边的 sayHi()函数是一个普通函数,没有事件对象
                    // 而我们的resize 函数是一个事件函数,事件函数本身就有一个默认的参数 e ,
                    // 这里只是将 e 写成了 arguments ,这样写既能够符合 apply 的规范写法,
                    // 又能够给普通函数传递事件处理函数的默认参数 e 
                    // 普通函数在拿到这个默认参数之后就能够进行相应的操作
                    canRun = true;
                }, 1000);
            };
        }
        // 模拟需要节流的目标函数
        function sayHi(e) {
            console.log(e.target.innerWidth, e.target.innerHeight);
        }
        // 全局状态下监听
        window.addEventListener('resize', throttle(sayHi));
    </script>
</body>

</html>

恭喜你!看懂了 ### 节流 ###

如有不当之处,请各位朋友留言,批评指正!不胜感激! thank you~~~!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值