1 防抖(debounce)
单位时间内,频繁触发事件,只执行最后一次
【例子】王者荣耀英雄回城,只要被打断就要重新来
【应用场景】1. 搜索框搜索输入。只需用户最后一次输入完,再发送请求;2. 手机号、邮箱验证输入检测。
【需求】鼠标在盒子上滑动,并在盒子上显示滑动的次数
如果不使用防抖, 那么在盒子上的数字将会增加的非常快,如果是一些非常消耗性能的代码,可能会造成卡顿
1.1 使用 lodash 库实现防抖
无论滑动多少下 1s后才加1
语法:
_.debounce(func, [wait=0], [options={}])
func: 需要防抖的函数
wait: 延迟执行的时间
options: 配置对象
【代码】
const box = document.querySelector('.box')
let i = 1
function mouseMove() {// 如果里面存在大量消耗性能的代码,比如dom操作,比如数据处理,可能造成卡顿box.innerHTML = i++
}
box.addEventListener('mousemove', _.debounce(mouseMove, 1000))
1.2 手写防抖函数
【代码】
// 2.手写防抖函数// 核心是利用 setTimeOut 定时器实现// 2.1 声明定时器变量// 2.2 每次鼠标移动(事件触发)的时候先判断是否有定时器,如果有则清除以前的定时器// 2.3 如果没有定时器,则开启定时器,存入定时器变量里面// 2.4 在定时器里面写函数调用function debounce(fn, t) {let timer = nullreturn function () {if (timer) clearTimeout(timer)timer = setTimeout(function () {fn()}, t)}}box.addEventListener('mousemove', debounce(mouseMove, 500))
2 节流(throttle)
单位时间内,频繁触发事件,只执行一次
【例子】王者荣耀英雄技能,在那段时间内你只能用一次该技能,下次想要用,需要等待技能冷却完毕
【应用场景】1. 鼠标连续触发某事件(如鼠标连续点击),只在单位时间内执行一次; 2. 监听滚动事件scroll,每隔100ms执行一次,实现防抖效果;3.页面尺寸缩放 resize
2.1 使用lodash库实现节流
语法:
_.throttle(func, [wait=0], [options={}])
func: 需要节流的事件处理函数
wait: 在wait 秒内最多执行func 一次的函数
box.addEventListener('mousemove', _.throttle(mouseMove, 3000))
2.2 手写节流函数
// 2.2 手写节流函数// 核心是利用 setTimeOut 定时器实现// 2.2.1 声明定时器变量// 2.2.2 每次鼠标移动(事件触发)的时候先判断是否有定时器,如果有则清除以前的定时器// 2.2.3 如果没有定时器,则开启定时器,存入定时器变量里面// 2.2.4 在定时器里面写函数调用function throttle(fn, t) {let timer = nullreturn function () {if (timer) returntimer = setTimeout(function () {fn()timer = null}, t)}}box.addEventListener('mousemove', throttle(mouseMove, 3000))
因为在 setTimeout 中是无法删除定时器的,因为定时器还在运作,所以使用timer = null
3 节流案例
【需求】在一个网页中播放了一个视频,在我下次再次打开这个页面时,视频的进度在我之前播放到的位置
【补充知识】
【代码】
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script><script>// ontimeupdate 触发频次太高,我们设定 1秒钟触发一次const video = document.querySelector('.video video')video.ontimeupdate = _.throttle(() => {// console.log(video.currentTime)// 把间隔一秒就把当前播放时间存储到本地存储中localStorage.setItem('currentTime', video.currentTime)}, 1000)// 打开页面的时候,从本地存储中获取当前播放时间video.onloadeddata = () => {video.currentTime = localStorage.getItem('currentTime') || 0}</script>