防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
思路:每次触发事件时都取消之前的延时调用方法。
使用的本质:不允许某一行为触发。
节流: 高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。
思路:每次触发事件时都判断当前是否有等待执行的延时函数。
使用的本质:允许某一行为触发,但是触发的频率不能太高。
防抖:防止抖动的意思,也就是不抖动时才进行相应的处理。比如一根拉直的弹簧,我们拨动一下它就会抖动,过一段时间后弹簧会恢复到平静的状态(从拨动弹簧使其抖动到恢复平静的时长就是代码例子的ms值)。在这个过程中,拨动弹簧的这一行为假设为事件被触发(代码中的input事件被触发),当弹簧恢复平静时我们再执行事件处理函数(代码中的sayHi函数)。基于以上假设,当我们在弹簧还没恢复到平静状态时,又不断地拨动它(清除了原来的setTimeout,并重新开始计时),因为弹簧还没恢复到平静,那么事件处理函数就一直不会被执行。只有当我们拨动它,并且之后再也不动它(也就是最后一次触发),等它恢复到平静状态时(setTimeout时间到达),事件处理函数才会被执行。
节流:控制住流量的意思,流量没达到一定的程度就不进行相应的处理。比如我们用水桶去接水,水龙头保持以不变的流量出水(即事件不断被触发),只有当水桶里的水满的时候(setTimeout时间到达),我们才将装满水的水桶拿走(执行事件处理函数),使用完后再拿这个空桶继续接水(重新开始计时)。
从以上的比喻中我们可以知道,防抖是用来处理那些离散的事件(拨动弹簧),节流是用来处理那些连续的事件(水一直在流出),这样我们就可以根据事件触发是离散型的还是连续型的来判断使用防抖还是节流啦(当然还要考虑实际需求)!
防抖应用的例子:判断用户的输入情况,只在用户停止输入一段时间后再进行判断。
节流应用的例子:滚动页面垂直滚动条,判断是否滚动到页面底部。
utis/fun.js
//防抖
export const debounce=(fn, wait=1000)=> {
var timer = null;
return function () {
var context = this
var args = arguments
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(function () {
fn.apply(context, args)
}, wait)
}
}
//节流
export const throttle = (fn, gapTime=500)=> {
let _lastTime = null;
return function () {
let _nowTime = + new Date()
if (_nowTime - _lastTime > gapTime || !_lastTime) {
fn();
_lastTime = _nowTime
}
}
}
home.js
import React, { Component } from 'react'
import {debounce,throttle} from '../../utis/debounce'
export default class index extends Component{
constructor(props) {
console.log(props)
super(props)
this.state = {
tip: null,
trigerTimes: 1
}
this.isPhoneLegal = debounce(this.isPhoneLegal, 1000)
}
handleKeyUp = (e) => {
console.log(e.target.value)
this.isPhoneLegal(e.target.value) // 对用户输入进行判断
}
isPhoneLegal = (phone) => {
const phoneRegexp = /^1([38]\d|5[0-35-9]|7[3678])\d{8}$/
const { trigerTimes } = this.state
if(phoneRegexp.test(phone)) {
this.setState({
tip: `手机号符合规则!`,
trigerTimes: 0
})
} else {
this.setState({
tip: `手机号有误, 触发了:${trigerTimes}次`,
trigerTimes: trigerTimes + 1
})
}
}
render (){
return
{this.state.tip}
}
}