全球共有10多个国家和地区1000多个平台,20万+商户使用
前端性能优化 | 防抖与节流
作者: 何坤隆 发布时间: 2023-11-11 1274 分类专栏: 前端开发
为什么要做性能优化?性能优化到底有多重要? 性能优是为了提供更好的用户体验、加快网站加载速度、提高搜索引擎排名、节省服务器资源、适应多种设备和网络环境等方面的需求。通过不断优化性能,可以提高用户满意度、增加网站流量提高业务效果。
同时性能优化是把双刃剑,有好的一面也有坏的一面。好的一面就是可以能提升网站性能,坏的一面就是配置多,代码复杂,或者要遵守的规则太多。并且某些性能优化规则并不适用所有场景,所以也并不是一味的追求性能优化,而是需要谨慎使用。
防抖和节流是JavaScript
中常用的两种性能优化方式。面试中我们也会经常碰到。它们的作用是减少函数的执行次数,以提高代码的性能。本文将详细介绍防抖和节流的定义、原理和实现方法,并讨论如何在具体功能中使用它们。
如下图所示,防抖(Debounce
)是指在事件被触发 delay
时间后再执行回调 function
函数,如果在这设置的 delay
时间内事件又被触发,则重新计时。这可以使用在些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。
如下图所示,节流(Throttle
)是指规定一个单位时间(延迟 delay
时间),在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll
函数的事件监听上,通过事件节流来降低事件调用的频率。
搜索框实时搜索:当用户在搜索框中输入内容时,通常需要实时进行搜索。使用防抖函数可以延迟搜索请求的发送,只在用户停止输入一段时间后才真正发送请求,避免频繁的请求操作。
表单输入验证:在表单输入过程中,每次用户输入都可能触发验证操作。使用防抖函数可以延迟触发验证操作,只在用户输入完毕一段时间后进行验证,避免频繁的验证操作。
浏览器窗口调整事件:当用户调整浏览器窗口大小时,会触发resize
事件。使用防抖函数可以延迟resize
事件的触发,只在用户停止调整窗口一段时间后才执行对应的操作,避免频繁的计算和布局操作。
鼠标移动事件:在一些特定的交互场景中,需要根据鼠标的移动位置做出相应的交互。使用防抖函数可以延迟鼠标移动事件的触发,只在用户停止移鼠标一段时间后才执行相应的操作,避免过度频繁的操作。
以用户搜索框实时搜索请求后台为例,我们来详细看一下:
<div class="box">
输入事件没有进行防抖处理:<input type="text" id="demo" name="demo">
</div>
<script>
// 模拟请求
function req(value){
console.warn("request: " + value + ", time: " + new Date());
}
const inputBox = document.getElementById("demo");
inputBox.addEventListener("keyup",e=>{
req(e.target.value);
})
</script>
上面结果所示,只要我们在输入框中每次输入文字,那么就会触发一次模拟请求,这对于用户和开发者而言都是不好的体验和资源的浪费。
思考: 我们想到每次用户输入文字都是需要一定时间的,那么我们可以定义在规定时间进行完整输入才能进行请求,这样我们可以减轻对后台的压力。
防抖规则:
500ms
内输入文字按下键盘都不会触发请求事件,而是在输入框的定时器500ms
停止输入后发送请求
优化: 我们改造一下上述的代码,监听我们的输入框,在500ms
内连续输入,不进行任何操作,500ms
后发送一次请求。
<div class="box">
输入事件进行防抖处理:<input type="text" id="demo" name="demo">
</div>
<script>
// 模拟请求
function req(value){
console.warn("request: " + value + ", time: " + new Date());
}
const inputBox = document.getElementById("demo");
inputBox.addEventListener("keyup",e=>{
debounce(() => req(e.target.value), 500);
})
</script>
从上面的运行结果可以看出,在500ms
内在输入框中连续输入文字都不会触发请求事件,而是在输入框的定时器500ms
停止输入后发送请求。
实现原理很简单,就是对于频繁输入的输入框请求事件添加定时器进行计数,在指定时间内进行频繁输入并不会进行请求,而是在指定时间间隔内停止输入才会执行函数。
当停止输入但在此定时器计数时间内,会重新进行触发请求事件。
页面滚动事件:当用户滚动页面时,会频繁触发滚动事件。使用节流函数可以控制滚动事件的触发频率,避免过多的计算和渲染操作,提高页面的性能和流畅度。
窗口大小调整:当用户调整浏览器窗口大小时,会不断触发resize
事件。使用节流函数可以限制resize
事件的触发频率,以避免过度计算和布局操作。
频繁点击按钮:在某些场景下,点击按钮可能会触发重复的提交操作。使用节流函数可以限制按钮点击的触发频率,防止重复的提交。
动画场景: 避免短时间内多次触发动画引起性能问题
拖拽场景: 在某些场景下,频繁触发位置变动会造成性能问题,固定时间内只执行一次,防止超高频次触发位置变动
以频繁点击按钮防止重复提交为例子,我们来详细看一下:
<button id="demo" style="margin: 50px;">点击按钮</button></button>
<script>
let value = 1
// 模拟请求
function req(){
console.warn("request: " + value++ + ", time: " + new Date());
}
const ele = document.getElementById("demo");
ele.addEventListener("click", (e) => {
req()
});
</script>
上面结果所示,只要我们点击按钮,那么就会触发一次模拟请求,这除了对于服务器的压力以外,还会造成多次数据提交,有可能会造成数据重复的风险。
节流规则:
1000ms
内频繁点击按钮,只能成功一次
优化: 按钮频繁多次点击时,为了避免用户多次请求,做了节流限制,在规定一个1000ms
时间内,只能有一次点击成功的触发动作。
<button id="demo" style="margin: 50px;">点击按钮</button></button>
<script>
let value = 1
// 模拟请求
function req(){
console.warn("request: " + value++ + ", time: " + new Date());
}
const ele = document.getElementById("demo");
ele.addEventListener("click", (e) => {
throttle(() => req(), 1000)
});
</script>
从上面的运行结果可以看出,在1000ms
内按钮连续多次点击,只有一次成功。
实现思路
/**
* @desc 防抖函数:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
* @param {Function} func 函数
* @param {Number} wait 延迟执行毫秒数
* @param {Boolean} immediate true 表示立即执行,false 表示非立即执行
*/
let timeout
function debounce(func, wait = 500, immediate = false) {
// 清除定时器
if (timeout) clearTimeout(timeout)
// 立即执行,此类情况一般用不到
if (immediate) {
let callNow = !timeout
timeout = setTimeout(() => {
timeout = null
}, wait)
if (callNow) typeof func === 'function' && func()
} else {
// 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
timeout = setTimeout(() => {
typeof func === 'function' && func()
}, wait)
}
}
实现思路
/**
* @desc 节流函数:在一定时间内,只能触发一次
* @param {Function} func 函数
* @param {Number} wait 延迟执行毫秒数
*/
let previous = 0
function throttle(func, wait = 500) {
let now = Date.now()
if (now - previous > wait) {
typeof func === 'function' && func()
previous = now
}
}
在本篇文章中,我们了解了JavaScript中的防抖和节流优化技术。这两种技术都是为了解决频繁触发的事件而产生的性能问题,通过限制事件触发的频率,提升页面性能和用户体验。
我们首先介绍了防抖和节流的定义和区别,防抖是指在一段时间内,只执行最后一次触发的事件,而节流是指一段时间内,固定间隔触发事件。然后,我们详细阐述了防抖和节流的原理和实现方式。
在实际应用中,我们经常遇到需要使用防抖和节流来优化用户交互、滚动事件、输入框输入等场景。通过合理地防抖和节流,我们可以减少冗余的计算和渲染,提高页面的流畅性和响应速度。
在文章的结尾,提供了一些常见的优化库和工具,方便开发者快速应用于实际开发中。
通过本文的学习,希望大家能够充分理解防抖和节流的原理,并且能够根实际情况合理应用于自己的项目,提升页面的性能和用户体验。
何坤隆
小当家ISV,重庆APP开发,小程序开发,软件系统开发 地址:重庆市南岸区南坪万达广场写字楼2栋19-6 联系电话:023-81361879
ICP备案号:渝ICP备15003473-1 增值电信业务许可证: 渝B2-15003473 渝公网安备 50010802005103号
友情链接: APP定制开发 小程序定制开发 MagicShop商城系统 酒类行业解决方案
重庆小当家互联网信息技术有限公司