防抖节流
目的
解决短时间内高频触发某事件导致响应速度跟不上频率,从而出现延迟、停顿、卡死等问题
防抖
1. 概念
高频触发事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
2. 实现
-
方式:每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法,其中使用到闭包来缓存定时器
-
缺点:如果事件在规定的时间间隔内被不断的触发,则调用方法会被不断的延迟
3. 应用
- 登录、发短信时,用户点击多次,只发送一次请求
- resize浏览器窗口变化,1秒内只重绘一次图表
- 文本编辑器实时保存,当无任何更改操作一秒后进行保存
/utils/methods:公共函数
/**
* @description 函数防抖 (delay秒内只执行最后一次点击)
* @param {Function} fn 要防抖的函数
* @param {Number} delay 时间
* @returns {Function}
* @constructor
*/
export const debounce = (fn, t) => {
const delay = t || 500
let timer
return function () {
const args = arguments
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
timer = null
fn.apply(this, args)
}, delay)
}
}
// vue中使用
import { debounce } from '@/utils/methods'
mounted() {
// 监听滚动事件
window.addEventListener('scroll', () => {
const param = '传参'
this.getData(param)
})
},
methods: {
// 定义防抖方法
getData: debounce(function (val) { this.handle(val) }, 1000),
handle (val) {
console.error('防抖函数', val)
},
}
节流
1. 概念
触发高频事件后n秒内函数也只会执行一次,但如果一直被触发,则每n秒执行一次,相当于稀释函数的执行频率
2. 实现
2.1 定时器
方式:触发事件时,判断如果没有定时器,则延迟n秒执行函数且执行函数后将定时器清除,保证高频触发事件每n秒只执行1次
/**
* @description 函数节流(每interval秒只执行一次)
* @param {Function} fn 要节流的函数
* @param {Number} interval 时间
* @returns {Function}
* @constructor
*/
export const throttleTimer = (fn, t) => {
const interval = t || 500
let timer = null
return function () {
var context = this
var args = arguments
if (!timer) {
timer = setTimeout(function () {
fn.apply(context, args)
timer = null
}, interval)
}
}
}
// vue中使用
import { throttleTimer } from '@/utils/methods'
mounted() {
// 监听屏幕变化事件
window.addEventListener('resize', () => {
const param = '传参'
this.getData(param)
})
},
methods: {
// 定义防抖方法
getData: throttleTimer(function (val) { this.handle(val) }, 1000),
handle (val) {
console.error('节流函数', val)
},
}
2.2 时间戳
方式:触发事件时,如果当前时间和上一次触发时间差大于设定的高频时间间隔n,则立即执行函数,否则清除定时器,延迟n秒后执行函数
/utils/methods:公共函数
/**
* @description 函数节流(每interval秒只执行一次)
* @param {Function} fn 要节流的函数
* @param {Number} interval 时间
* @returns {Function}
* @constructor
*/
export const throttleTimestamp = (fn, t) => {
let last
let timer
const interval = t || 500
return function () {
const args = arguments
const now = +new Date()
if (last && now - last < interval) {
clearTimeout(timer)
timer = setTimeout(() => {
last = now
fn.apply(this, args)
}, interval)
} else {
last = now
fn.apply(this, args)
}
}
}
// vue中使用
import { throttleTimestamp } from '@/utils/methods'
mounted() {
// 监听屏幕变化事件
window.addEventListener('resize', () => {
const param = '传参'
this.getData(param)
})
},
methods: {
// 定义防抖方法
getData: throttleTimestamp(function (val) { this.handle(val) }, 1000),
handle (val) {
console.error('节流函数', val)
},
}
3. 应用
- input输入框实时搜索:每隔1秒发送请求获取搜索列表
- scroll滚动事件:每隔一秒计算一次位置信息
- 浏览器播放事件,每隔一秒计算进度条