详细介绍 地址
https://segmentfault.com/a/1190000018428170https://segmentfault.com/a/1190000018428170
防抖:
高频率触发的事件,在指定的单位时间内,只响应最后一次,如果在指定的时间在触发,则重新计算时间(后面触发的事件执行,替代了前面的事件)
全局this 修改为input的this
<body>
<input id="input1" type="text">
<script>
const input1 = document.getElementById('input1')
function debounce(fn, delay) {
let timer = null
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
//模拟触发change事件
fn.apply(this, arguments)
// 清空计时器
timer = null
}, delay);
}
}
input1.addEventListener('keyup', debounce(() => {
console.log(input1.value)
}, 500))
</script>
function debounce(fn,delay){
let timer = null //借助闭包
return function() {
if(timer){
clearTimeout(timer) //进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
timer = setTimeout(fn,delay)
}else{
timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时,那么就开始一个计时
}
}
}
其实 time = setTimeout(fn,delay)是一定会执行的,所以可以稍微简化下:
//简化版
function debounce(fn, delay) {
let tiemr = null
return function () {
if (tiemr) {
clearTimeout(tiemr)
} tiemr = setTimeout(fn, delay)
}
}
节流:
高频率触发的事件,在指定的单位时间内,只响应第一次(前面触发的执行前,忽略后面的事件)
function throttle(fn,time) {
let canRun = true; // 通过闭包保存一个标记
return function () {
if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
canRun = false; // 立即设置为false
setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
fn.apply(this, arguments);
// 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
canRun = true;
}, time);
};
}
function sayHi(e) {
console.log(e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener('resize', throttle(sayHi,500));
vue 防抖
<template>
<div>
<input type="text" :value="value" @input="changeInput">
</div>
</template>
<script>
export default {
data() {
return {
value: '',
ms: 3000,
timeID: ''
};
},
methods: {
changeInput(e) {
this.value = e.target.value;
}
},
watch: {
value(newValue, oldValue) {
if (newValue !== oldValue) {
// 数据变化了,执行逻辑,这里做好防抖。
this.ms = 3000;
clearTimeout(this.timeID);
this.timeID = setTimeout(() => {
console.log(this.value);
}, this.ms)
}
}
}
}
</script>