概念:

防抖是延迟执行,而节流是间隔执行,函数节流即每隔一段时间就执行一次,实现原理为 设置一个定时器,约定XX毫秒后执行事件,如果时间到了,那么执行函数并重置定时器,和防抖的区别在于,防抖每次触发事件都重置定时器,而节流在定时器到时间后再清空定时器。函数防抖的情况下,函数将一直推迟执行,造成不会被执行的效果;函数节流的情况下,函数将每个 n 秒执行一次。

一、防抖

在src目录下创建一个名为utils的文件夹,在文件夹下新建一个名为util.js的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 防抖:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
* @param func 要执行的回调函数
* @param wait 延时的时间
* @param immediate 是否立即执行
*/
let timeout = null;

export function debounce(func, wait = 500, immediate = false) {
// 清除定时器
if (timeout !== null) clearTimeout(timeout);
// 立即执行,此类情况一般用不到
if (immediate) {
const callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait);
if (callNow) typeof func === 'function' && func();
} else {
// 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
timeout = setTimeout(() => {
typeof func === 'function' && func();
}, wait);
}
}

二、节流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* 节流:在一定时间内,只能触发一次
* @param func 要执行的回调函数
* @param wait 延时的时间
* @param immediate 是否立即执行
*/
let timer,
flag;

export function throttle(func, wait = 500, immediate = true) {
if (immediate) {
if (!flag) {
flag = true;
// 如果是立即执行,则在wait毫秒内开始时执行
typeof func === 'function' && func();
timer = setTimeout(() => {
flag = false;
}, wait);
}
} else {
if (!flag) {
flag = true;
// 如果是非立即执行,则在wait毫秒内的结束处执行
timer = setTimeout(() => {
flag = false;
typeof func === 'function' && func();
}, wait);
}
}
}

三、在vue中使用

我们可以在main.js通过mixin全局混入来避免在每个vue文件里重复引入防抖、节流方法,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import {
debounce,
throttle
} from '@/utils/util';

Vue.mixin({
methods: {
/** 防抖:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
* @param func 要执行的回调函数
* @param wait 延时的时间
* @param immediate 是否立即执行
*/
fixDebounce(func, wait = 500, immediate = false) {
debounce(func, wait, immediate);
},
/** 节流:在一定时间内,只能触发一次
* @param func 要执行的回调函数
* @param wait 延时的时间
* @param immediate 是否立即执行
*/
fixThrottle(func, wait = 500, immediate = true) {
throttle(func, wait, immediate);
}
}
})

new Vue({
router,
store,
render: (h) => h(App)
}).$mount('#app')

调用:

1
2
3
4
5
6
7
<el-input
v-model="searchKey"
size="mini"
prefix-icon="el-icon-search"
@input="fixDebounce(fun,1000)"
placeholder="写字楼/小区/学校等">
</el-input>

注意:fixDebounce(fun,1000)中,fun后面不能加()