场景
节流的常见场景
在日常开发中,我们可能会遇见这么一种场景,一个元素的宽高需要跟随窗口的变化来变化;例如:当我们使用 element-UI 的表格组件时,表格的数据是不确定的,但我们需要固定表头,当内容过多时可以对内容进行滚动,这时我们就需要给组件提供一个具体的高度,但是浏览器的窗口宽高是会变化的(人为的去缩放浏览器),这就要求我们去监听窗口的变化,当窗口宽高变化的时候,执行一个函数,重新计算浏览器宽高,让表格的高度发生变化
防抖的常见场景
日常开发过程中,我们可能会遇到实时搜索的场景;例如:用户在搜索框输入了内容,我们要根据内容实时的给用户推荐相关的搜索语,让用户选择。
问题
在上述两个场景中,有一个共同点就是函数被高频的调用,无论是实时窗口变化还是输入框的实时变化,都会超高频的触发 resize
和 input
事件,但不同的是,在节流的场景中,我们更希望的是在一定的时间段,计算窗口宽高的函数只被执行一次;在防抖的场景中,我们更希望用户输入结束后,再根据输入内容,给用户推荐搜索语。
解决方法
节流的代码解决
对于节流的场景,我们的目标是在一定的时间段内,函数只被执行一次;我们假设在窗口变化过程中,每200毫秒计算一次浏览器宽高,也就是每200毫秒修改一次元素大小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const getWindowHeight = () => { const {width,height} = window.screen; console.log('浏览器宽度为:',width, '浏览器高度为:', height); }
const throttle = (fn) => { let timeNo; return () => { console.log('窗口变化'); if(timeNo) return; timeNo = setTimeout(() => { fn() clearTimeout(timeNo); timeNo = null; }, 200); } }
window.addEventListener('resize', throttle(getWindowHeight))
|
防抖的代码解决
对于防抖的场景,我们的目标是,在高频被触发时,以最后一次触发,去执行函数;我们假定时间间隔是200毫秒,也就是说用户在搜索框输入内容触发 input
事件后,等200毫秒后再去拿输入框内容,在这200毫秒内用户输入了,我们就重新计时等待;
1 2 3 4 5 6 7 8 9 10 11 12 13
| const input = document.querySelector('#input'); const debounce = () => { let timeNo; return (e) => { clearTimeout(timeNo); timeNo = setTimeout(() => { const {target: {value}} = e; console.log('输入框的值为',value) clearTimeout(timeNo); },200) } } input.addEventListener('input', debounce());
|
概念
函数节流 即在一个事件被连续的触发过程中,以一个固定的时间长度,间隔的去执行一个函数;
函数防抖 即在一个事件被连续的触发过程中,只在最后一次触发时执行一个函数
优化
对函数节流的通用封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
const throttle = (fn, Intervals, ...args) => { let timeNo; return (...params) => { if(timeNo) return; timeNo = setTimeout(() => { fn(...args,...params) clearTimeout(timeNo); timeNo = null; }, Intervals); } }
const obj = { name: '张三', fun(params, str) { console.log(this.name, '接收参数', params, str); } } window.addEventListener('resize', throttle(obj.fun.bind(this), 200, {text: '最外面传的第一个参数'}, '最外面传的第二个参数'))
|
对函数防抖的通用封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
const debounce = (fn, Intervals, ...args) => { let timeNo; return (...params) => { clearTimeout(timeNo); timeNo = setTimeout(() => { fn(...args,...params) clearTimeout(timeNo); }, Intervals) } }
const getInputValue = (e) => { const {target: {value}} = e; console.log('输入框的值为',value) } const input = document.querySelector('#input'); input.addEventListener('input', debounce(getInputValue,200));
|