JS奇淫巧技:防抖函数与节流函数
应用场景
实际工作中,我们经常性的会通过监听某些事件完成对应的需求,比如:
- 通过监听 scroll 事件,检测滚动位置,根据滚动位置显示返回顶部按钮
- 通过监听 resize 事件,对某些自适应页面调整DOM的渲染(通过CSS实现的自适应不再此范围内)
- 通过监听 keyup 事件,监听文字输入并调用接口进行模糊匹配
- ...
常规实现,以监听 scroll 事件为例
我们先来看一下scroll事件的触发频率
window.onscroll = function () {
//滚动条位置
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
效果如下:
从效果上,我们可以看到,在页面滚动的时候,会在短时间内触发多次绑定事件。
我们知道DOM操作是很耗费性能的,如果在监听中,做了一些DOM操作,那无疑会给浏览器造成大量性能损失。
下面我们进入主题,一起来探究,如何对此进行优化。
函数防抖
定义:多次触发事件后,事件处理函数只执行一次,并且是在触发操作结束时执行。
原理:对处理函数进行延时操作,若设定的延时到来之前,再次触发事件,则清除上一次的延时操作定时器,重新定时。
scroll 的一个简单例子
let timer;
window.onscroll = function () {
if(timer){
clearTimeout(timer)
}
timer = setTimeout(function () {
//滚动条位置
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
timer = undefined;
},200)
}
效果如下:滚动结束触发事件
防抖函数的封装使用
/**
* 防抖函数
* @param method 事件触发的操作
* @param delay 多少毫秒内连续触发事件,不会执行
* @returns {Function}
*/
function debounce(method,delay) {
let timer = null;
return function () {
let self = this,
args = arguments;
timer && clearTimeout(timer);
timer = setTimeout(function () {
method.apply(self,args);
},delay);
}
}
window.onscroll = debounce(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
},200)
函数防抖的适用性:
通过上面的例子,我们知道我们可以通过函数防抖,解决了多次触发事件时的性能问题。
比如,我们在监听滚动条位置,控制是否显示返回顶部按钮时,就可以将防抖函数应用其中。
但依然有些功能并不适用:
当我们做图片懒加载(lazyload)时,需要通过滚动位置,实时显示图片时,如果使用防抖函数,懒加载(lazyload)函数将会不断被延时,
只有停下来的时候才会被执行,对于这种需要实时触发事件的情况,就显得不是很友好了。
下面开始介绍函数节流,通过设定时间片,控制事件函数间断性的触发。
函数节流
定义:触发函数事件后,短时间间隔内无法连续调用,只有上一次函数执行后,过了规定的时间间隔,才能进行下一次的函数调用。
原理:对处理函数进行延时操作,若设定的延时到来之前,再次触发事件,则清除上一次的延时操作定时器,重新定时。
scroll 的一个简单例子
);
}
}
效果如下:每隔500毫秒触发一次事件
防抖函数的封装使用
/**
* 节流函数
* @param method 事件触发的操作
* @param mustRunDelay 间隔多少毫秒需要触发一次事件
*/
function throttle(method, mustRunDelay) {
let timer,
args = arguments,
start;
return function loop() {
let self = this;
let now = Date.now();
if(!start){
start = now;
}
if(timer){
clearTimeout(timer);
}
if(now - start >= mustRunDelay){
method.apply(self, args);
start = now;
}else {
timer = setTimeout(function () {
loop.apply(self, args);
}, 50);
}
}
}
window.onscroll = throttle(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
},800)
文中如果出现错误,希望小伙伴们可以谅解,更希望可以给予指正
JS奇淫巧技:防抖函数与节流函数的更多相关文章
- JS 奇淫巧技 转
1. 在 String.prototype.replace 方法中使用 /g 和 /i 标志位 令很多 JavaScript 初学者意外的是,字符串的 replace 方法并不会 替换所有匹配的子串— ...
- [javascript 实践篇]——那些你不知道的“奇淫巧技”
1. 空(null, undefined)验证 刚开始,我是比较蠢的验证(我还真是这样子验证的) if (variable1 !== null || variable1 !== undefined | ...
- [asp.net mvc 奇淫巧技] 05 - 扩展ScriptBundle,支持混淆加密javascript
一.需求: 在web开发中,经常会处理javascript的一些问题,其中就包括js的压缩,合并,发布版本以及混淆加密等等问题.在asp.net 开发中我们使用ScriptBundle已经可以解决ja ...
- [手写系列] Spirit带你实现防抖函数和节流函数
前言 防抖函数和节流函数,无论是写业务的时候还是面试的时候,想必大家已经听过很多次了吧.但是大家在用到的时候,有了解过他们之间的区别嘛,他们是如何实现的呢?还是说只是简单的调用下像lodash和und ...
- [asp.net mvc 奇淫巧技] 01 - 封装上下文 - 在View中获取自定义的上下文
我们在asp.net 开发中已经封装了最强大的HttpContext,我们可以在HttpContext中可以获取到几乎任何想获取的东西,也可以在HttpContext写入需要返回客户端的信息.但是这些 ...
- [asp.net mvc 奇淫巧技] 02 - 巧用Razor引擎在Action内生成Html代码
在web开发中经常会遇到在内部代码中获取Html,这些Html是需要和数据进行一起渲染.并不是直接把Html代码返回给客户端.这样的做法有很多应用场景,例如分页.Ajax一次性获取几段Html片段.生 ...
- [asp.net mvc 奇淫巧技] 03 - 枚举特性扩展解决枚举命名问题和支持HtmlHelper
一.需求 我们在开发中经常会遇到一些枚举,而且这些枚举类型可能会在表单中的下拉中,或者单选按钮中会用到等. 这样用是没问题的,但是用过的人都知道一个问题,就是枚举的命名问题,当然有很多人枚举直接中文命 ...
- [asp.net mvc 奇淫巧技] 04 - 你真的会用Action的模型绑定吗?
在QQ群或者一些程序的交流平台,经常会有人问:我怎么传一个数组在Action中接收.我传的数组为什么Action的model中接收不到.或者我在ajax的data中设置了一些数组,为什么后台还是接收不 ...
- [asp.net mvc 奇淫巧技] 06 - 也许你的项目同一个用户的请求都是同步的
一.感慨 很久前看到一篇博客中有句话大致的意思是:“asp.net 程序性能低下的主要原因是开发人员技术参差不齐”,当时看到这句话不以为然,然而时间过的越久接触的.net 开发人员越多就越认同这句话: ...
随机推荐
- boost::this_thread::sleep_for()死锁
boost::this_thread::sleep_for()会死锁 (金庆的专栏) 发现睡眠1ms很容易死锁.boost::this_thread::sleep_for(boost::chrono: ...
- iOS 百度地图计算两个点时间的距离
最近在解项目bug,更新地位城市的时候有个错误,后来想在位置改变多少距离之后,再取更新位置,这个功能去年做过.但是又忘记了! 所以还是记录一下吧. 百度地图提供了一个方法: BMKMapPointFo ...
- HBase Master启动过程
master启动过程: -->首先初始化HMaster -->创建一个rpcServer,其中并启动 -->启动一个Listener线程,功能是监听client的请求,将请求放入ni ...
- C# /VB.NET 创建PDF项目符号列表和多级编号列表
使用项目符号和编号,可以让文档的层次结构更清晰.更有条理,也更容易突出重点.在编辑文档的过程中,我个人也比较偏爱项目标号来标注文章重点信息.在之前的文章中,介绍了如何在Word中来创建项目标号和编号列 ...
- RHEL7.0 Docker离线安装以及实战笔记
1.概述 最近在琢磨一个事--在RHEL 7.0系统上离线安装使用Docker.然后配置JAVAEE环境,发布Web服务.在网上查了资料,大多数是在线安装的,其他的要么是环境不同,要么资料包找不到了. ...
- poi excel 常用操作
基本 Workbook wb= new HSSFWorkbook(); Sheet sheet = wb.createSheet("sheetName"); Row row = s ...
- Mybatis解决jdbc编程的问题
1.1.1 Mybatis解决jdbc编程的问题 1. 数据库链接创建.释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题. 解决:在SqlMapConfig.xml中配置 ...
- .net 模糊匹配路径
string[] fileNames = Directory.GetFiles("D:/", "*1.txt"); // 路径,模糊文件名 : 返回符合的文件名 ...
- 从has no method 'tmpl'谈起
最近做一个相对比较功能专业化的应用系统,其中今天Leader提出的功能修改需求有点smart table的意思,其中有个界面修改由于用Dom操作太麻烦了,于是想用用很久之前在学习jQuery API中 ...
- 走进netty
三月份开始看公司RPC框架的源码,发现如果要折腾明白,网络通讯这块知识必不可少.于是从如下几点开始逐步研究. 一.基础知识篇 1.Unix下5种I/O模型 Linux的内核将所有外部设备都看作一个文件 ...