防抖三个阶段
1.1s后执行1次,多次点击不执行
2.首次点击执行,多次点击只执行第一次,(执行1次)
3.首次点击执行,多次点击只执行最后一次,(执行2次)
1-
<template> <div> <el-button id="btn">catchMe</el-button> </div> </template> <script> export default { mounted() { let btn = document.getElementById("btn"); btn.addEventListener("click", trigger(real, 1000)); function trigger(fn, delay) { let time = null; return function () { // *FirstClick execute. // let firstClick = !time; // firstClick && fn(...arguments); if (time) { clearTimeout(time); } // reset timer(定时器clock) // now time is not null, firstClick is null // But it should be null when the next time to click. time = setTimeout(() => { // *firstClick become the start flag to clickMethod. fn(...arguments); // time = null; // **When timer clear and the last click need to be executed. // !firstClick && fn(...arguments); }, delay); }; } function real(e) { console.log("debounce", e); } }, }; </script>
2-
<template> <div> <el-button id="btn">catchMe</el-button> </div> </template> <script> export default { mounted() { let btn = document.getElementById("btn"); btn.addEventListener("click", trigger(real, 1000)); function trigger(fn, delay) { let time = null; return function () { // *FirstClick execute. let firstClick = !time; firstClick && fn(...arguments); if (time) { clearTimeout(time); } // reset timer(定时器clock) // now time is not null, firstClick is null // But it should be null when the next time to click. time = setTimeout(() => { // *firstClick become the start flag to clickMethod. // fn(...arguments); time = null; // **When timer clear and the last click need to be executed. // !firstClick && fn(...arguments); }, delay); }; } function real(e) { console.log("debounce", e); } }, }; </script>
3-
<template> <div> <el-button id="btn">catchMe</el-button> </div> </template> <script> export default { mounted() { let btn = document.getElementById("btn"); btn.addEventListener("click", trigger(real, 1000)); function trigger(fn, delay) { let time = null; return function () { // *FirstClick execute. let firstClick = !time; firstClick && fn(...arguments); if (time) { clearTimeout(time); } // reset timer(定时器clock) // now time is not null, firstClick is null // But it should be null when the next time to click. time = setTimeout(() => { // *firstClick become the start flag to clickMethod. // fn(...arguments); time = null; // **When timer clear and the last click need to be executed. !firstClick && fn(...arguments); }, delay); }; } function real(e) { console.log("debounce", e); } }, }; </script>
节流
高强度点击按钮,每1s生成一次提示
时间戳版本
<template> <div> <el-button id="btn">needYou</el-button> </div> </template> <script> export default { mounted() { let btn = document.getElementById("btn"); btn.addEventListener("click", trigger(real, 1000)); function trigger(fn, delay) { // last executed time let bef = 0; return function () { // get recent time let now = new Date().getTime(); // When time has arrived, it exectues and bef reset. if (now - bef > delay) { fn(...arguments); bef = now; } }; } function real() { console.log("I need you."); } }, }; </script>
定时器版本
<template> <div> <el-button id="btn">needYou</el-button> </div> </template> <script> export default { mounted() { let btn = document.getElementById("btn"); btn.addEventListener("click", trigger(real, 1000)); function trigger(fn, delay) { let flag = true; return function () { // Frist click, it will delay to execute. flag && setTimeout(() => { fn(...arguments); flag = true; }, delay); // Flag become false, timer will not start. // Until the next time click. flag = false; }; } function real() { console.log("I need you."); } }, }; </script>
使用
对一个el-button使用防抖,多次点击只执行首次
// DebounceBtn.vue
<template> <div> <el-button class="click">click</el-button> count:{{ count }} </div> </template> <script> import { debounce } from "../utils/utils"; export default { data() { return { count: 0, }; }, mounted() { let btn = document.getElementsByClassName("click")[0]; btn.addEventListener("click", debounce(this.handleClick, 1000)); }, methods: { handleClick() { this.count = this.count + 1; }, }, }; </script> <style> </style>
// /utils/utils.js
/** * @param {Function} func * @param {number} wait * @param {boolean} immediate * @return {*} */ export function debounce(func, wait) { console.log('debounce count'); let time = null; return function () { let firstClick = !time; firstClick && func(...arguments); if (time) { clearTimeout(time); } time = setTimeout(() => { time = null; }, wait) } }
总结——
防抖就是通过setTimeout 的方式,在一定的时间间隔内,将多次触发变成一次触发 。
节流:就是减少一段时间的触发频率。
防抖与节流最大的区别就是,无论事件触发多么频繁,都可以保证在规定时间内可以执行一次执行函数。防抖首尾自定义执行,节流点击途中一直有隔着相应时间间隔的执行。