文章目录
防抖函数(可用于防止重复提交)
当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次, 如果设定时间到来之前,又触发了事件,就重新开始延时。也就是说当一个用户一直触发这个函数,且每次触发函数的间隔小于既定时间,那么防抖的情况下只会执行一次。
/**
* 防抖函数(可用于防止重复提交)
* 当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,
* 如果设定时间到来之前,又触发了事件,就重新开始延时。也就是说当一个用户一直触发这个函数,
* 且每次触发函数的间隔小于既定时间,那么防抖的情况下只会执行一次。
*
* @param func 执行函数
* @param wait 间隔时间
* @param immediate 立即执行
*/
function debounce(fn, wait, immediate) {
let timer;
return function() {
if (timer) clearTimeout(timer);
if (immediate) {
// 如果已经执行过,不再执行
var callNow = !timer;
timer = setTimeout(() => {
timer = null;
}, wait)
if (callNow) {
fn.apply(this, arguments)
}
} else {
timer = setTimeout(() => {
fn.apply(this, arguments)
}, wait);
}
}
}
节流函数
当持续触发事件时,保证在一定时间内只调用一次事件处理函数,意思就是说,假设一个用户一直触发这个函数,且每次触发小于既定值,函数节流会每隔这个时间调用一次
用一句话总结防抖和节流的区别:防抖是将多次执行变为最后一次执行,节流是将多次执行变为每隔一段时间执行
实现函数节流我们主要有两种方法:时间戳和定时器
/**
* 节流函数
* 当持续触发事件时,保证在一定时间内只调用一次事件处理函数,意思就是说,假设一个用户一直触发这个函数,且每次触发
* 小于既定值,函数节流会每隔这个时间调用一次
* 用一句话总结防抖和节流的区别:防抖是将多次执行变为最后一次执行,节流是将多次执行变为每隔一段时间执行
* 实现函数节流我们主要有两种方法:时间戳和定时器
*
* @param func 执行函数
* @param wait 间隔时间
* @param options 立即执行
* options中 leading:false 表示禁用第一次执行 trailing: false 表示禁用停止触发的回调
*/
function throttle(fn, wait, options = {}) {
let timer;
let previous = 0;
let throttled = function() {
let now = +new Date();
// remaining 不触发下一次函数的剩余时间
if (!previous && options.leading === false) previous = now;
let remaining = wait - (now - previous);
if (remaining < 0) {
if (timer) {
clearTimeout(timer);
timer = null;
}
previous = now;
fn.apply(this, arguments)
} else if (!timer && options.trailing !== false) {
timer = setTimeout(() => {
previous = options.leading === false ? 0 : new Date().getTime();
timer = null;
fn.apply(this, arguments);
}, remaining);
}
}
return throttled;
}
vue中调用防抖函数不生效的解决方法
import {debounce} from "../../util.js"
add(e){
debounce(function(){
console.log("点击")
},500)
}
}
最开始向上面这样写,会发现debounce函数执行了,但是其返回的一个延时函数并没有执行。仔细检查发现,没有调用执行其返回的一个函数。所以应该将调用处改为如下;
add(e){
// console.log("点击")
// delay(()=>{
// console.log("点击")
// },500)
debounce(function(){
console.log("点击")
},500)()//加括号表示调用其返回的那个函数
}
}
现在的问题
首先 如果以以上的方式 来存timer等外层变量 有两种情况使用保留 且不同组件不相互影响
1.组件中引入工具对象,可以同样选择在data中增加一个debounceFn:null句柄来保存这个闭包,然后在组件初始化阶段给设置好 如图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0QCYUjJs-1622432123960)(http://doc.tianbp.com/server/index.php?s=/api/attachment/visitFile/sign/fd653d47526726a5e5e54bc76ca76666)]
2.存到methods会相对好点(记得拆闭包)
methods: { handleInputChange:utl.debounce(function(){
console.log(this.inputText);
},1500)
},
watch: {
inputText(newVal) {
if (newVal !== "") {
// 经过节流
this.handleInputChange();
}
}
},
beforeDestroy() {
this.handleInputChange = null;
}
第二种 就是 timer等外层变量 作为全局变量
这样 就不会因为每次调用了都重置了 也不需要在组件去保留这个方法 只是作为全局 你要保证传入的时间内不会有第二个按钮被点击 不然依旧不会生效 因为 timer还存在
//公用方法里:
let timer;//放在公用方法外面 每次使用 都不会刷新
function debounce(fn, wait, immediate) {
}
如有更好的方式 欢迎指教