防抖 debounce

应用场景:监听一个输入框,文字变化触发change事件,不使用防抖,每次输入都会触发事件,使用防抖,等用户输入结束或暂停时才触发

  1. <input type="text" class="input">
  2. <script>
  3. const input = document.querySelector('.input')
  4. let timer = null
  5. input.addEventListener('keyup', () => {
  6. if (timer) {
  7. window.clearTimeout(timer)
  8. }
  9. timer = setTimeout(() => {
  10. console.log(input.value)
  11. timer = null
  12. }, 500)
  13. })
  14. </script>

封装成函数

  1. <input type="text" class="input">
  2. <script>
  3. const input = document.querySelector('.input')
  4. function debounce(fn, delay = 500) {
  5. let timer = null
  6. return function() {
  7. const context = this
  8. if (timer) {
  9. window.clearTimeout(timer)
  10. }
  11. timer = setTimeout(() => {
  12. fn.apply(context, arguments)
  13. timer = null
  14. }, delay)
  15. }
  16. }
  17. input.addEventListener('keyup', debounce(() => { console.log(input.value) }))
  18. </script>

节流 throttle

应用场景:拖拽一个元素时,要随时拿到该元素的拖拽位置,如果不想频繁触发导致卡顿,应使用节流,不论拖拽速度有多快,每隔100ms触发一次; 或者监听用户点击按钮,在一定时间内只有1次有效

  1. <div class="div" draggable="true"></div>
  2. <script>
  3. const div = document.querySelector('.div')
  4. let timer = null
  5. div.addEventListener('drag', (e) => {
  6. if (timer) {
  7. return
  8. }
  9. timer = setTimeout(()=> {
  10. console.log(e.offsetX, e.offsetY)
  11. timer = null
  12. }, 100)
  13. })
  14. </script>

封装成函数

  1. <div class="div" draggable="true"></div>
  2. <script>
  3. const div = document.querySelector('.div')
  4. function throttle(fn, delay = 100) {
  5. let timer = null
  6. return function () {
  7. const context = this
  8. if (timer) {
  9. return
  10. }
  11. timer = setTimeout(() => {
  12. fn.apply(context, arguments)
  13. timer = null
  14. }, delay)
  15. }
  16. }
  17. div.addEventListener('drag', throttle((e) => {
  18. console.log(e.offsetX, e.offsetY)
  19. }))
  20. </script>

节流写法二

  1. function throttle(fn, delay=3000) {
  2. let canUse = true
  3. return function() {
  4. if (canUse) {
  5. canUse = false
  6. fn.apply(this, arguments)
  7. window.setTimeout(() => canUse = true, delay)
  8. }
  9. }
  10. }
  11. const f = throttle((a) => console.log(a))
  12. f(1)
  13. f(1) // 不会执行