防抖函数:
- 要实现的效果是在页面的input中不停的输入内容,停止输入1秒钟后在控制台输出输入结果(进行相关的数据操作...)
要实现该效果需要用到定时器来触发相应的处理逻辑
- 但是在做的时候发现使用了setTimeout后依旧是输入一次就处理(输出)一次,只是有些延迟而已,这样就没有意义了
- 思路:需要将setTimeout存起来,然后每次input触发的时候就清除上一次存下的setTimeout,这样在最后一次触发的时候就只触发了一个setTimeout就实现了防抖的效果
- 实现方法:将setTimeout通过闭包的形式给存储起来,每次Input触发事件的时候使用clearTimeout清除上一个,代码如下:
<body>
<input type="text" id="int">
<script>
let int = document.querySelector('#int')
const logRes = function(){ //输出数据
console.log(int.value)
}
const debunce = function(callback ,delay){
let timer = null
return function(){
clearTimeout(timer) //清空上一次存储的定时器
timer = setTimeout(() => {
callback() //每次防抖结束要执行的回调方法
}, delay)
}
}
int.addEventListener('input', debunce(logRes, 1500))
</script>
</body>
节流函数
- 本次实现的效果是监听 window 的鼠标移动事件,第一次输出坐标后,保持移动,10秒内不再进行输出
思路:函数内部声明两个变量
last:用于记录,第一次/上一次输出坐标的时间戳,通过判断 last 的值来确认是不是第一次执行函数
- 如果第一次执行函数将当前的时间戳赋值给 last
- 如果 last 有数据,证明不是第一次执行,判断 now < last + delay 当前的时间是否满足大于 上次执行的时间+设定的节流延时时间 的条件,满足则证明已经超过了延时时间可以再次执行,如果不满足则不做任何操作。
- deferTimer:一个定时器
<body>
<script>
(function(){
console.log(arguments);
})()
const throttle = function(callback, delay){
let last //记录最后的时间
let deferTimer //定时器
return function(){
let that = this //向外查找,最终指向 window
let _args = arguments
let now = +new Date() //拿到现在的时间戳
//判断节流
//last 用于判断之前是否执行过,看是不是第一次执行
//now < last + delay 判断设置的时间有没有到,如果时间已经过了,就再执行一次,否则不执行回调
if (last && now < last + delay){ //不是第一次触发
clearTimeout(deferTimer) //清除定时器
deferTimer = setTimeout(() => { //重新计时
last = now //将最后一次计算的时间改写为当前时间
callback.apply(that, _args) //在这里直接调用callback是拿不到对应的数据的,使用 apply 将作用域指向 window
}, delay)
}else { //第一次触发
last = now
callback.apply(that,_args)
}
}
}
const moveFun = function(e){
console.log('鼠标距离页面页面横向距离',e.pageX);
console.log('鼠标距离页面页面纵向距离',e.pageY);
}
//添加监听事件
window.addEventListener('mousemove', throttle(moveFun, 3000))
</script>
</body>
是在vue项目中使用的防抖和节流函数:
const debounce =(func,delay)=>{
var timer = null;
return function() {
var context = this;
var args = arguments;
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(function() {
func.apply(context, args);
timer = null;
}, delay);
}
}
const throttle =(func,delay)=>{
var timer = null;
return function() {
var context = this;
var args = arguments;
if (!timer) {
timer = setTimeout(function() {
func.apply(context, args);
timer = null;
}, delay);
}
}
}
export { debounce,throttle }
调用方式:
<template>
<div>
<button @click="test">点我测试</button>
<button @click="logmsg">测试节流</button>
</div>
</template>
<script>
import request from '@/api/apiTest.js'
import { debounce,throttle } from '@/utils/debounce.js'
export default {
methods: {
//测试防抖
test: debounce(() => {
request.testGet('pc/fee/bill/load-scheme', {
name: 'sss'
}).then(res => {
console.log('请求成功', res);
}).catch(err => {
console.log('清iq失败', err);
})
}, 1500),
//测试节流
logmsg: throttle(() => {
console.log('test');
},1500)
}
}
</script>
<style>
</style>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。