IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 防抖(debounce) 和 节流(throttling) -> 正文阅读

[JavaScript知识库]防抖(debounce) 和 节流(throttling)

debounce的特点是当事件快速连续不断触发时,动作只会执行一次。

周期内有新事件触发,清除旧定时器,重置新定时器;这种方法,需要高频的创建定时器。

JavaScript 防抖 - Web前端工程师面试题讲解_哔哩哔哩_bilibiliJavaScript 防抖 - Web前端工程师面试题讲解https://www.bilibili.com/video/BV17b4y1X7yp/?spm_id_from=333.788

简单实现:

        <button id="btn" style="width: 100%;">按钮</button>

        const button = document.querySelector('button')
        function payMoney() {
            console.log('滴滴滴');
            console.log(this); // 不使用防抖函数this指向点击按钮
                               // 使用防抖函数this指向window
        }

        function debounce(fun,time) {
            let timer;
            return function() {
                let _this = this;
                let args = arguments
                clearTimeout(timer)
                timer = setTimeout(function() {
                    fun.apply(_this,args)
                },time)
            }
        }

        button.addEventListener('click',debounce(payMoney,1000))

        /* 
            function ebounce(func) {
                func()
            }
           难点1: 这样写的话,在定义监听函数的时候就直接执行了函数
           为了解决这个问题,使用高阶函数,在函数里面返回函数   
           function ebounce(func) {
                return function() {
                    func()
                }
            }   

            要进行延迟就相应的需要清除延时,为延时设置变量名,清除是使用 clearTimeout
            难点2: 清除以后在定义变量是会报错的    
            难点3: 1秒内多次执行,但是全部消息都陆续执行了
                  这里每次执行函数就是创建变量,清除延时,建立延时三个步骤;
                  而且每次点击的执行函数都是独立的,因为他们直接没有联系,
                  因此清除延时在这里完全不起作用;
                  要让他们直接有联系就需要利用作用域链了,也就是闭包;
                  把定义timer放到函数外
            难点4: this指向
            参数问题: js里函数没有设置参数是可以传入参数的
                    每一个执行函数有可能传入参数,而传入的参数是给payMoney函数使用的 

        */

封装一下:

        <button id="btn" style="width: 100%;">按钮</button>

        const button = document.querySelector('button')
        function payMoney() {
            console.log('滴滴滴');
            console.log(this); // 不使用防抖函数this指向点击按钮
                               // 使用防抖函数this指向window
        }

        function debounce(fun,wait) {
            let timer;
            let timerStamp;
            let _this;
            let args;
            let clear= () =>  {
                clearTimeout(timer)
            }
            let run = () => {
                timer = setTimeout(function() {
                    fun.apply(_this,args)
                },wait)
            }
            return function(){
                _this = this
                args = arguments
                let now = new Date().getTime()
                if(now-timerStamp < wait){
                    clear()
                }
                run()
                timerStamp = now
            }
        }

        button.addEventListener('click',debounce(payMoney,1000))

throttling,节流的策略是,固定周期内,只执行一次动作,若有新事件触发,不执行。周期结束后,又有事件触发,开始新的周期。

throttling的特点在连续高频触发事件时,动作会被定期执行,响应平滑。

JavaScript 节流 - Web前端工程师面试题讲解_哔哩哔哩_bilibiliJavaScript 节流 - Web前端工程师面试题讲解https://www.bilibili.com/video/BV11Z4y1c7C9/?spm_id_from=333.788

小实验:

f       function coloring() {
            let r = Math.floor(Math.random() * 225);
            let g = Math.floor(Math.random() * 225);
            let b = Math.floor(Math.random() * 225);
            document.body.style.background = `rgb(${r},${g},${b})`
        }
        function throttle(fun,delay) {
            let timer;
            return function() {
                let _this = this;
                let args = arguments
                if(timer){
                    return
                }
                timer = setTimeout(function() {
                    fun.apply(_this,args)
                    timer = null
                },delay)
            }
        }
        window.addEventListener('resize',throttle(coloring,1000))
        
        /*
            判断触发的事件是否在时间间隔内,如果在时间间隔内,不触发事件,如果不在,就出发事件.
            如果timer被赋值,也就是任务在等待执行,暂时不改变timer的值,如果没有值,就直接赋值
            if timer有值,直接返回, 没有值,进行赋值
        */

第二种写法:

        function coloring() {
            let r = Math.floor(Math.random() * 225);
            let g = Math.floor(Math.random() * 225);
            let b = Math.floor(Math.random() * 225);
            document.body.style.background = `rgb(${r},${g},${b})`
        }
        function throttle(fun,delay) {
            let pre = 0;
            return function() {
                let _this = this;
                let args = arguments
                let now = new Date()
                if(now - pre > delay){  
                // 当前时间减去上一次执行的时间,如果大于传入的时间就执行,否则不执行
                    setTimeout(function() {
                        fun.apply(_this,args)
                        pre = now
                    })
                }
            }
        }
        window.addEventListener('resize',throttle(coloring,1000))

封装1:

         var throttle = (fn, wait) => {
                let timer;
                let context, args;
            
                let run = () => {
                    timer=setTimeout(()=>{
                        fn.apply(context,args);
                        clearTimeout(timer);
                        timer=null;
                    },wait);
                }
            
                return function () {
                    context=this;
                    args=arguments;
                    if(!timer){
                        console.log("throttle, set");
                        run();
                    }else{
                        console.log("throttle, ignore");
                    }
                }
            
            }
        window.addEventListener('resize',throttle(coloring,1000))

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-18 17:32:01  更:2022-05-18 17:33:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:40:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码