JavaScript中的防抖与节流、在react class及hook中使用防抖与节流

函数防抖:函数被触发后过一段时间再执行,如果在这段时间内又被触发,则重新计时,即将多次高频操作优化为只在最后一次执行。应用场景为用户连续输入,只需要在输入结束后做一次校验即可,比如input搜索或校验。简而言之,就是在input请求时使用防抖。

function debounce(func, ms = 1000) {
  let timer;
  return function (...args) {
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      func.apply(this, args)
    }, ms)
  }
}

// 测试
const task = () => { console.log('run task') }
const debounceTask = debounce(task, 1000)
window.addEventListener('scroll', debounceTask)

 

函数节流:函数在一段时间内只能被触发一次,如果这段时间内被触发多次,则只有一次生效,即每隔一段时间执行一次,也就是降低频率,将高频操作优化成低频操作。应用场景为滚动条事件或窗口resize事件,通常每隔100-500ms执行一次。简而言之,就是在滚动条请求时使用节流。

function throttle(func, ms = 1000) {
  let canRun = true
  return function (...args) {
    if (!canRun) return
    canRun = false
    setTimeout(() => {
      func.apply(this, args)
      canRun = true
    }, ms)
  }
}

// 测试
const task = () => { console.log('run task') }
const throttleTask = throttle(task, 1000)
window.addEventListener('scroll', throttleTask)

 

防抖或节流一般使用:

import debounce from 'lodash/debounce'

debounce(()=>search(value), 500)

 

在类组件中使用防抖或节流:

import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import { Input } from 'antd';
import throttle from 'lodash/debounce';

class Search extends React.Component {
    constructor(props) {
      super(props)
      this.handleSearch = throttle(this.handleOnChange, 200);
    }
 
    handleOnChange = (e) => {
      console.log(e.target.value)
    }
    render() {
        return (
            <Input onChange={this.handleSearch} />
        )
    }
}

ReactDOM.render(
  <Search />,
  document.getElementById('container'),
);

 

在函数组件中使用防抖或节流,需要使用useCallback或useRef缓存变量和方法:

import React, { useCallback } from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import { Input } from 'antd';
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';

const Search = () => {

  const handleOnChange = (e) => {
    console.log(e.target.value)
  }
  const handleSearch = useCallback(throttle((e) => handleOnChange(e), 500), [])

  return (<Input onChange={handleSearch}  placeholder="Basic usage" />)
}

ReactDOM.render(<Search />, document.getElementById('container'));

import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import { Input } from 'antd';
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';

const Search = () => {

  const handleOnChange = (e) => {
    console.log(e.target.value)
  }
  const handleSearch = useRef(throttle((e) => handleOnChange(e), 500)).current

  return (<Input onChange={handleSearch}  placeholder="Basic usage" />)
}

ReactDOM.render(<Search />, document.getElementById('container'));

 

在函数组件里使用debounce,不使用lodash:

import { useEffect } from 'react'
function useDebounce(fn, delay, dep=[]) {
   useEffect(()=>{
      let timer;
      timer = setTimeout(fn, delay);
      return ()=>clearTimeout(timer);
   }, [...dep]
  )
}
export default useDebounce
// 调用
useDebounce(()=>search(value), 500, [value])

import { useRef } from 'react'
function useDebounce(fn, delay) {
    const timer = useRef(null);
    return () => {
        clearTimeout(timer.current);
        timer.current = setTimeout(fn, delay);
    }
}
export default useDebounce
// 调用
const debounceSearch = useDebounce(() => handleParams(params), 500)
useEffect(()=>{debounceSearch()},[value]

 

posted @ 2021-10-18 19:04  starlog  阅读(1043)  评论(0编辑  收藏  举报