防抖和节流又是什么东西?
用来处理某个工作短时间内过于频繁触发的场景,只是根据不同的处理方式有不同的说法。
应用场景:防止用户连续多次点击提交表单、监听滚动、窗口大小、输入框内容校验等高频事件
简要概念:
节流 即在一个事件被连续的触发过程中,以一个固定的时间长度,间隔的去执行一个函数;
防抖 即在一个事件被连续的触发过程中,只在最后一次触发时执行一个函数
防抖:某个函数在短时间内只执行最后一次。
意思也就是说,函数被触发时,需要先延迟,在延迟的时间内,如果再次被触发,则取消之前的延迟,重新开始延迟。这样就能达到,只响应最后一次,其余的请求都过滤掉。
这种处理方式有很多实际的应用场景:比如对输入框数据的校验处理,没必要每输入一个字符就校验一遍;
节流:某个函数在指定时间段内只执行第一次,直到指定时间段结束,周而复始。
跟防抖不一样的是,节流是指定时间段内只执行第一次,也就是这段时间内,只需要响应第一次的请求即可,后续的请求都会被过滤掉,直到下个时间段,重新来过,周而复始。
应用场景:Android 里的屏幕刷新机制,每个帧(16.6ms)内,不管进行了多少次请求界面刷新的操作,只需响应第一次的请求,去向底层注册监听帧信号即可。因为接收到帧信号后,是通过遍历 View 树来刷新界面,所以注册的动作只需要进行一次就够了。Vue 的虚拟 DOM 的刷新也是类似的机制。
写一个utils.js:
/*
* 自己写一个防抖函数吧 (注意维护同一个timer)
* */
防抖代码
export function debounce(fn, delay) {
var timer = null;// //定义一个变量作为等会清除对象;记录上一次的延时器
return function() {
var args = arguments;
var that = this;
clearTimeout(timer) // 清除上一次延时器
timer = setTimeout(function() {
fn.apply(that,args)
}, delay);
}
}
/*
* 自己写一个节流函数吧
* */
export function throttle (fn, delay) {
let clickNow = true
return function () {
if (clickNow) {
clickNow = false
setTimeout(function () {
//为什么要通过 apply 这种修改函数内部 this 的方式来调用原函数?直接 fn() 不行吗?
//这里之所以要通过 call 方式来修改原函数的 this,
//是因为,原函数通过参数进行传递时,是只会被当做普通函数处理,不管原函数本来是否挂载在某个对象上。
//所以,如果 debounce 内部直接以 fn() 方式调用原函数,会导致原函数的内部 this 指向发生变化。
//这边执行了节流函数fn()
fn.apply(this, arguments)
clickNow = true
}, delay)
}
}
}
使用:
clickFn: throttle(function () {
console.log('节流测试')
}, 1000),
vue中使用防抖例子
搜索排版代码
<input type="text" placeholder="输入用户名" v-model="userName" v-on:input="userSearch">
在公共的js文件utils.js中添加防抖函数如下:
export default {
debounce(fn, delay) {
var timer = null;// //定义一个变量作为等会清除对象;记录上一次的延时器
return function() {
var args = arguments;
var that = this;
clearTimeout(timer) // 清除上一次延时器
timer = setTimeout(function() {
fn.apply(that,args)
}, delay);
}
}
}
防抖搜索功能
import utils from "@/js/utils";
export default {
methods: {
//使用防抖函数
uaerSearch: utils.debounce(function() {
this.$axios.get('接口',this.userName).then(res=>{})
},200)
}
}