// 代码1
  // 每次value改变,就会发出一次请求
  <input onChange={handleChange} />
  const handleChange = async ({target: { value }}) => {
    const res = await search({ keyword: value })
  }
  // 代码2
  // 通过定时器。设置时间间隔500ms执行一次请求
  <input onChange={handleChange} />
  let timer = null
  const handleChange = ({target: { value }}) => {
    if(timer) {
      clearTimeout(timer)
      timer = null
    }
    timer = setTimeout(async () => {
      const res = await search({ keyword: value })
    }, 500)
  }
  // 代码3
  // 公共函数抽取
  /*
    应有的功能
    1. 参数和返回值如何传递?
    2. 防抖之后函数是否可以立即执行?
    3. 防抖的函数是否可以取消?
  */
  const debounce = (func, wait = 0) => {
    let timer = null
    let args
    function debounced(...age) {
      args = arg
      if(timer) {
        clearTimeout(timer)
        timer = null
      }
      // 以promise形式返回函数执行结果
      return new Promise((res, rej) => {
        timer = setTimeout(async () => {
          try {
            const result = await func.apply(this, args)
            res(result)
          } catch (e) {
            rej(e)
          }
        }, wait)
      })
    }
    // 取消方法
    function cancel() {
      clearTimeout(timer)
      timer = null
    }
    // 立即执行
    function fulsh() {
      cancel()
      return func.apply(this, args)
    }
    debounced.cancel = cancel
    debounced.flush = flush
    return debounced
  }
 
下面3中监听方式的区别
方式1和方式2属于DOM0标准,通过这种方式进行事件监听会覆盖之前的事件监听函数
方式3属于DOM2标准,同一元素上的事件监听函数互不影响,而且可以独立取消,调用顺序和监听顺序一致
方式1:<input type=‘text‘ onclick=‘click()‘ />
方式2:document.querySelecter(‘input‘).onClick = function(e) {}
方式3:document.querySelecter(‘input‘).addEventListener(‘click‘, function(e) {})
  <ul class=‘list‘>
    <li class=‘item‘>item1<span class=‘edit‘>编辑</span><span class=‘delete‘>删除</span></li>
    <li class=‘item‘>item1<span class=‘edit‘>编辑</span><span class=‘delete‘>删除</span></li>
    <li class=‘item‘>item1<span class=‘edit‘>编辑</span><span class=‘delete‘>删除</span></li>
    ...
  </ul>
  const ul = document.querySelector(‘.list‘)
  ul.addEventListener(‘click‘, e => {
    const t = e.target || e.srcElement
    if (t.classList.contains(‘item‘)) {
      // 接口请求处理业务逻辑
    } else {
      id = t.parentElement.id
      if (t.classList.contains(‘edit‘)) {
        edit(id)
      } else if (t.classList.contains(‘delete‘)) {
        del(id)
      }
    }
  })
原文:https://www.cnblogs.com/sk-3/p/13983028.html