防抖
指触发事件n秒后再执行回调,若在n秒之内再次被触发,则重新计时。
手写实现防抖
function debounce(fn, delay) {
let timer
return function() {
let that = this
let args = arguments
if(timer) clearTimeout(timer)
timer = setTimeout(function() {
fn.apply(that, args)
}, delay)
}
}
应用
由定义可知,防抖主要是为了解决事件频繁触发的问题,且仅采取频繁触发的最后一次操作。
常用场景:
- 输入框联想。
- 窗口
resize事件。
以vue3为例, 针对el-input的@input事件进行防抖,接口临时写的,没有返回值,主要还是让大家感受下防抖前后的现象。还有在线Demo,亲身体验,点我 🙌。
<template>
<div class="debounce-throttle">
<div class="case-one">
<div class="title">未防抖Input</div>
<el-input v-model="caseStateOne" placeholder="请输入内容" @input="notDebounceSearchAsync"></el-input>
</div>
<div class="case-two">
<div class="title">防抖Input</div>
<el-input v-model="caseStateTwo" placeholder="请输入内容" @input="debounceSearchAsync"></el-input>
</div>
</div>
</template>
<script setup>
import { getDebounceOrThrottle } from '@/api/api.js'
import { ref } from 'vue'
let caseStateOne = ref('')
let caseStateTwo = ref('')
/**
* @description: 防抖函数
* @param {*} fn
* @param {*} delay
* @return {*}
*/
const debounce = function (fn, delay) {
let timer
return function () {
let that = this
let args = arguments
if (timer) clearTimeout(timer)
timer = setTimeout(function () {
fn.apply(that, args)
}, delay)
}
}
/**
* @description: 未防抖远程搜索函数
* @param {*} queryString
* @param {*} cb
* @return {*}
*/
const notDebounceSearchAsync = async function () {
let result = await getDebounceOrThrottle()
console.log('result:', result)
}
/**
* @description: 防抖远程搜索函数
* @param {*} queryString
* @param {*} cb
* @return {*}
*/
const debounceSearchAsync = debounce(async function () {
let result = await getDebounceOrThrottle()
console.log('result:', result)
}, 1000)
</script>
lodash 中的 debounce
lodash是一个JavaScript工具库,也提供了防抖函数。既然有成熟的库,为何不用呢?
import _ from 'lodash'
const lodashDebounceSearchAsync = _.debounce(async function () {
let result = await getDebounceOrThrottle()
console.log('result:', result)
}, 1000)
节流
规定在n秒内,只能触发一次回调。若在n秒内触发多次函数,只有第一次生效
手写节流
定时器写法
function throttle(fn, delay) {
let timer
return function() {
let that = this
let args = arguments
if(timer) return
timer = setTimeout(function() {
fn.apply(that, args)
timer = null
}, delay)
}
}
时间戳写法
function throttle(fn, delay) {
let last = 0
return function() {
let that = this
let args = arguments
let now = +new Date()
if(now - last > delay) {
fn.apply(that, delay)
last = now
}
}
}
应用
由定义可知,节流也是为了解决事件频繁触发的问题,且仅采取频繁触发的第一次操作。
常用操作:
- 鼠标交互事件
- 滚动事件
以vue3为例, 针对el-button的@click事件进行防抖,接口临时写的,没有返回值,主要还是让大家感受下防抖前后的现象。还有在线Demo,亲身体验,点我🙌。
<template>
<div class="debounce-throttle">
<div class="case">
<div class="title">未节流</div>
<el-button @click="notThrottleSearchAsync">点我</el-button>
</div>
<div class="case">
<div class="title">节流</div>
<el-button @click="throttleSearchAsync">点我</el-button>
</div>
<div class="case">
<div class="title">lodash节流</div>
<el-button @click="lodashThrottleSearchAsync">点我</el-button>
</div>
</template>
<script setup>
import { getDebounceOrThrottle } from '@/api/api.js'
import { ref } from 'vue'
/**
* @description: 节流点击函数
* @param {*} queryString
* @param {*} cb
* @return {*}
*/
const throttleSearchAsync = throttle(async function () {
let result = await getDebounceOrThrottle()
console.log('result:', result)
}, 1000)
/**
* @description: lodash节流点击函数
* @param {*} queryString
* @param {*} cb
* @return {*}
*/
const lodashThrottleSearchAsync = _.throttle(async function () {
let result = await getDebounceOrThrottle()
console.log('result:', result)
}, 1000)
/**
* @description: 未节流点击函数
* @param {*} queryString
* @param {*} cb
* @return {*}
*/
const notThrottleSearchAsync = async function () {
let result = await getDebounceOrThrottle()
console.log('result:', result)
}
</script>
lodash 中的 throttle
import _ from 'lodash'
const lodashThrottleSearchAsync = _.throttle(async function () {
let result = await getDebounceOrThrottle()
console.log('result:', result)
}, 1000)