函数防抖(debounce):当持续触发函数时,函数不执行,间隔一段时间后再执行。 防抖即防止抖动,这里的函数防抖时防止函数多次执行,抖动时高频率且无规律的,如果高频率的触发函数势必会对性能造成影响,因此,为防止高频触发函数,我们要做函数防抖处理,举个例子:input的输入,每次input输入后都需要去数据库比对当前输入的值是否存在,用户一直在输入,如果每次输入就要去数据库比对那触发就太频繁了,为此我们可以加防抖,当用户不再输入后间隔一段时间再去执行相应的函数。
函数节流(throttle):当持续触发函数时,保证一段时间内只执行一次函数。节流即节省流量,比如水龙头放水,把水龙头关小,水流量就会降低,这样就能保证即放水又不会浪费。举个例子:scroll事件,用户下拉加载数据,一直刷新,一秒钟操作了十回,但一秒钟内只执行一回,这样保证一秒钟时间内,至少执行了一回,又不频繁触发函数。
以上就是函数防抖和节流的大致介绍,刚开始接触防抖和节流觉得很高大上,后来看了一些博客介绍之后有了自己的理解,我觉得结合实际例子来理解概念会更容易一些,将这些应用到我们的功能开发中,更能理解其用处和含义。
vue中的函数防抖,看了很多博客,都是直接贴的代码,不是特别容易理解,我就针对自己在项目中用到的情况,简单写一下,比想象中的要简单,一起来看看吧。
函数防抖
实际应用:input输入,每次输入值之后去数据库比对是否存在,当不输入后一段时间再执行函数。这里省略了函数,只打印input的值。
<template>
<div style="margin: 20px;">
<el-input v-model="inputVal"/>
</div>
</template>
<script>
export default {
name: 'Test',
data() {
return {
inputVal: '',
timer: null
}
},
watch: {
inputVal() {
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = null
this.timer = setTimeout(() => {
this.handleJudge()
}, 1000)
}
},
methods: {
handleJudge() {
console.log(this.inputVal)
}
}
}
</script>
我们现在来分析一下,其实防抖就是为了不再触发后一段时间内再执行,核心在于定时器的应用,每次触发函数,清空定时器,直到不再触发函数后,间隔1000ms,执行定时器内的函数。
函数节流
实际应用:按钮的点击,用户短时间内多次点击,只执行一次点击函数。
<template>
<div style="margin: 20px;">
<el-button @click="handleClick()">click</el-button>
</div>
</template>
<script>
export default {
name: 'Test',
data() {
return {
timer2: null,
switchFlag: true
}
},
methods: {
handleClick() {
if (!this.switchFlag) {
return
}
this.switchFlag = false
this.timer2 = setTimeout(() => {
console.log('节流示例')
this.switchFlag = true
}, 1000)
}
}
}
</script>
我们现在来分析一下,其实节流就是一段时间内只执行一次函数,期间多次执行都不予以处理,实现这个功能我们需要定义一个开关和一个定时器,默认开关为开,执行一次函数后,开关置为关,再次执行,判断开关状态,为关则返回,不再向下执行,定时器1000ms后,触发函数,并把开关置为开,回到一开始的状态。
以上是函数防抖和节流的针对性应用,在一个项目中我们这样用肯定是不行的,所以还要封装成公用方法,精简我们的代码,下面贴2段经典常用的防抖和节流的代码。
/**
* 函数防抖 (只执行最后一次点击)
* @param fn
* @param delay
* @returns {Function}
* @constructor
*/
export const Debounce = (fn, t) => {
let delay = t || 500
let timer
return function () {
let args = arguments
if(timer){
clearTimeout(timer)
}
timer = setTimeout(() => {
timer = null
fn.apply(this, args)
}, delay)
}
};
/**
* 函数节流
* @param fn
* @param interval
* @returns {Function}
* @constructor
*/
export const Throttle = (fn, t) => {
let last
let timer
let interval = t || 500
return function () {
let args = arguments
let 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中使用的话,将2个方法放到公用方法的js里,并导出,应用如下:
<template>
<div style="margin: 20px;">
<input v-model="keyword" type="text" @keyup="appSearch">
</div>
</template>
<script>
import { Debounce } from '@/commonFunction/common'
export default {
name: 'Test',
data() {
return {
keyword: ''
}
},
methods: {
appSearch: Debounce (function() {
this.getAppList()
}, 1000),
getAppList() {
console.log(this.keyword)
}
}
}
</script>
最一开始查询有关防抖和节流的时候,出现的都是直接贴代码的帖子,并且都没有分析,可能也是自己基础比较欠缺,趁此又补充了一波,挺好。我们来分析一下防抖经典示例中的代码。
export const Debounce = (fn, t) => {
let delay = t || 500
let timer
return function () {
let args = arguments
if(timer){
clearTimeout(timer)
}
timer = setTimeout(() => {
timer = null
fn.apply(this, args)
}, delay)
}
};
不知道是不是有很多人和我一样 fn.apply(this,args) 看不懂,为此,我查了关于arguments的相关资料,又查了apply相关的资料,终于在MDN上找到了回答,MDN上关于apply的用法有这样一段。
好好看几遍这段话,调用函数时,为函数指定一个this对象,谁调用这个函数this就指向谁,使用apply,就可以继承不用再重复写该方法。
来到我们的例子中看一下,我一直觉得打印功能是非常棒的功能,尤其在我们并不了解某些功能和含义的时候。哪里不会打印哪里,妈妈再也不用担心我的学习。
export const Debounce = (fn, t) => {
let delay = t || 500
let timer
return function () {
let args = arguments
if(timer){
clearTimeout(timer)
}
timer = setTimeout(() => {
timer = null
fn.apply(this, args)
console.log(fn)
console.log(this)
console.log(args)
}, delay)
}
};
我们分别打印 fn、this、和arguments
可以看到fn即为我们作为参数传入的函数,this为调用该Debounce方法的vue组件,arguments为vue中调用该Debounce方法的getAppList()函数的相关参数。
根据打印结果再结合MDN上关于apply的解释,我们可以这样认定 fn.apply(this,arguments) 的作用在于使调用Debounce函数的vue组件中的方法指向正确,this指向当前组件本身,因为我们将Debounce写成了公共方法,因此会被多个组件调用,这样this的指向就不明确了,为了保证this都是指向当前调用Debounce函数的组件自身而将this绑定到调用的组件上,说白了就是一句话,哪个组件调用方法,this就指向哪个组件。
关于防抖和节流的细节分析已经有很多博客了,这里就不再说了,里边还涉及很多知识点,在下一篇博客中,针对防抖节流函数中应用到的知识点进行详细补充说明。 下面附上一篇我看过还不错的文章,可以帮助大家理解。