一、什么是函数防抖

概念:函数防抖(debounce),就是指触发事件后,在 n 秒内函数只能执行一次,如果触发事件后在 n 秒内又触发了事件,则会重新计算函数延执行时间。

举个栗子,坐电梯的时候,如果电梯检测到有人进来(触发事件),就会多等待 10 秒,此时如果又有人进来(10秒之内重复触发事件),那么电梯就会再多等待 10 秒。在上述例子中,电梯在检测到有人进入 10 秒钟之后,才会关闭电梯门开始运行,因此,“函数防抖”的关键在于,在 一个事件 发生 一定时间 之后,才执行 特定动作。

二、为什么需要函数防抖

  前端开发过程中,有一些事件,常见的例如,onresize,scroll,mousemove ,mousehover 等,会被频繁触发(短时间内多次触发),不做限制的话,有可能一秒之内执行几十次、几百次,如果在这些函数内部执行了其他函数,尤其是执行了操作 DOM 的函数(浏览器操作 DOM 是很耗费性能的),那不仅会浪费计算机资源,还会降低程序运行速度,甚至造成浏览器卡死、崩溃。这种问题显然是致命的。

除此之外,短时间内重复的 ajax 调用不仅会造成数据关系的混乱,还会造成网络拥塞,增加服务器压力,显然这个问题也是需要解决的。

三、函数防抖如何解决上述问题

根据上面对问题的分析,细细思索,可以想到如下解决方案。

函数防抖的要点,是需要一个 setTimeout 来辅助实现,延迟运行需要执行的代码。如果方法多次触发,则把上次记录的延迟执行代码用 clearTimeout 清掉,重新开始计时。若计时期间事件没有被重新触发,等延迟时间计时完毕,则执行目标代码。

四、函数防抖的代码实现

根据以上分析,我们对 “函数防抖” 来进行简单的代码实现,如下:

function debounce(fn,wait){
var timer = null;
return function(){
if(timer !== null){
clearTimeout(timer);
}
timer = setTimeout(fn,wait);
}
} function handle(){
console.log(Math.random());
} window.addEventListener("resize",debounce(handle,1000));

js

 // //  防抖函数
debounce(func, delay=150){
let timer = null
return function(...args){
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
func.apply(this,args)
}, delay);
}
}, //better-scroll的刷新
const refresh = debounce(this.$refs.scroll.refresh,100) refresh()

vue

防抖函数在一个项目中可能多个地方都可能使用,建议写在一个公共工具的util.js文件里面,在需要使用的文件里面导入函数,直接使用。

以上js部分有效,,vue部分使用了better-scroll(注意,函数触发方式为 “resize”,改变窗口大小,观察浏览器控制台的变化)。

五、函数节流的使用场景

函数防抖一般用在什么情况之下呢?一般用在,连续的事件只需触发一次回调的场合。具体有:

  1. 搜索框搜索输入。只需用户最后一次输入完,再发送请求;
  2. 用户名、手机号、邮箱输入验证;
  3. 浏览器窗口大小改变后,只需窗口调整完后,再执行 resize 事件中的代码,防止重复渲染。

目前遇到过的用处就是这些,理解了原理与实现思路,小伙伴可以把它运用在任何需要的场合,提高代码质量。

总结

函数防抖其实是分为 “立即执行版” 和 “非立即执行版” 的,根据字面意思就可以发现他们的差别,所谓立即执行版就是 触发事件后函数不会立即执行,而是在 n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。 而 “非立即执行版” 指的是 触发事件后函数会立即执行,然后 n 秒内不触发事件才能继续执行函数的效果。。

在开发过程中,我们需要根据不同的场景来决定我们需要使用哪一个版本的防抖函数,一般来讲上述的防抖函数都能满足大部分的场景需求。但我们也可以将非立即执行版和立即执行版的防抖函数结合起来,实现最终的双剑合璧版本的防抖函数,以下为小伙伴们做了简单的实现:

/**
* @desc 函数防抖---“立即执行版本” 和 “非立即执行版本” 的组合版本
* @param func 需要执行的函数
* @param wait 延迟执行时间(毫秒)
* @param immediate---true 表立即执行,false 表非立即执行
**/
function debounce(func,wait,immediate) {
let timer; return function () {
let context = this;
let args = arguments; if (timer) clearTimeout(timer);
if (immediate) {
var callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait)
if (callNow) func.apply(context, args)
} else {
timer = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
} function handle(){
console.log(Math.random());
} // window.addEventListener("mousemove",debounce(handle,1000,true)); // 调用立即执行版本
window.addEventListener("mousemove",debounce(handle,1000,false)); // 调用非立即执行版本

js防抖函数的更多相关文章

  1. JS 防抖函数和节流函数

    文章转载自:木上有水 什么是防抖?什么是节流? 工作中我们经常会用一些方法监听某些事件的完成,比如scroll.resize.keyup等. 常规事件触发的时候,比如scroll,会在短时间内触发多次 ...

  2. JS奇淫巧技:防抖函数与节流函数

    应用场景 实际工作中,我们经常性的会通过监听某些事件完成对应的需求,比如: 通过监听 scroll 事件,检测滚动位置,根据滚动位置显示返回顶部按钮 通过监听 resize 事件,对某些自适应页面调整 ...

  3. JS节流和防抖函数

    一. 实现一个节流函数 // 思路:在规定时间内只触发一次function throttle (fn, delay) {  // 利用闭包保存时间  let prev = Date.now()  re ...

  4. js实现防抖函数和节流函数

    防抖函数(debounce) 含义:防抖函数指的是在特定的时间内没有再次触发,才得以进行接下来的函数运行: 用途:当window.onresize不断的调整大小的时候,为了避免不断的重排与重绘,可以用 ...

  5. js节流与防抖函数封装

    js节流与防抖函数封装 常见应用场景: window的 resize 和 scroll 事件: 文字输入时的 keyup 事件: 元素拖拽.移动时的 mousemove 事件: 防抖 定义:多次触发事 ...

  6. 2019 面试准备 - JS 防抖与节流 (超级 重要!!!!!)

    Hello 小伙伴们,如果觉得本文还不错,记得给个 star , 你们的 star 是我学习的动力!GitHub 地址 本文涉及知识点: 防抖与节流 重绘与回流 浏览器解析 URL DNS 域名解析 ...

  7. 深入理解JS防抖与节流

    参考博客:JS防抖和节流,感谢作者的用心分享 日常开发过程中,滚动事件做复杂计算频繁调用回调函数很可能会造成页面的卡顿,这时候我们更希望把多次计算合并成一次,只操作一个精确点,JS把这种方式称为deb ...

  8. vue实现手机号码的校验(防抖函数的应用场景)

    上一篇博文我们讲到了节流函数的应用场景,我们知道了节流函数可以用在模糊查询.scroller.onresize等场景:今天这篇我们来讲防抖函数的应用场景:: 通过上一篇博文的学习,我们知道了防抖函数的 ...

  9. JS常用函数原理的实现

    本文针对目前常见的面试题,实现了相应方法的核心原理,部分边界细节未处理.后续也会持续更新,希望对你有所帮助. 1.实现一个call函数 // 思路:将要改变this指向的方法挂到目标this上执行并返 ...

随机推荐

  1. 《机器学习_02_线性模型_Logistic回归》

    import numpy as np import os os.chdir('../') from ml_models import utils import matplotlib.pyplot as ...

  2. linux常用命令---centOS7的管理服务(针对yum安装的)

    centOS7的管理服务(针对yum安装的)

  3. InnoDB存储引擎的高级特性大盘点

    InnoDB作为mysql数据库最常用的存储引擎,自然包含了其独有的很多特性.如相比于memory.MyISAM引擎,InnoDB支持行级锁.事务等都是比较重要的特性. 本文将盘点下InnoDB处理事 ...

  4. elasticsearch7.X x-pack破解

    简介: x-pack是elasticsearch的一个收费的扩展包,将权限管理,警告,监视等功能捆绑在一个易于安装的软件包中,x-pack被设计为一个无缝的工作,但是你可以轻松的启用或者关闭一些功能. ...

  5. iOS开发图片选择

    一行代码搞定图片选择 // // gzhPhotoManager.h // 图片选择 // // Created by 郭志贺 on 2020/5/26. // Copyright © 2020 郭志 ...

  6. GPG配置、命令、实例与apt-key密钥测试

    环境 Ubuntu18.04 gpg version 2.24 参考文档 GnuPG (简体中文) 例子文档 阮一峰 key Management 简介 他人用公钥来加密,自己用私钥来解密 自己用私钥 ...

  7. 二、Spring装配Bean

    内容 声明bean 构造器注入和Setter方法注入 装配Bean 控制bean的创建和销毁 关键词 装配(wiring) 组件扫描(component scanning) 自动装配(AutoWiri ...

  8. [ES6系列-05]字符串相关操作更方便

    [原创] 码路工人 Coder-Power 大家好,这里是码路工人有力量,我是码路工人,你们是力量. github-pages 博客园cnblogs 今天的内容是,关于 ES6 JavaScript ...

  9. Android_存储访问框架SAF

    概念 存储访问框架---Storage Access Framework (SAF),这是在Android4.4(API level 19)之后引入的. 借助 SAF,用户可轻松在其所有首选文档存储提 ...

  10. 循序渐进VUE+Element 前端应用开发(4)--- 获取后端数据及产品信息页面的处理

    在前面随笔<循序渐进VUE+Element 前端应用开发(3)--- 动态菜单和路由的关联处理>中介绍了在Vue + Element整合框架中,实现了动态菜单和动态路由的处理,从而可以根据 ...