實現防抖節流 - 使用drag拖拽事件+input keydown事件模擬場景

    爲了加深本身對防抖+節流的理解,實現兩個簡單的案例來加深本身的印象。css

1、函數節流(throttle)

經過實現一個拖拽Dom元素小案例來加深對函數節流的理解html

  • 情景:當drag拖拽事件執行,1秒內調用屢次DragFn函數。
  • 實現效果:若是1秒內執行了屢次函數,那麼函數1秒只能執行一次(5s執行5次)。

  • drag.js - 示例code
"use strict";

// 函數節流(throttle) - 情景:當drag拖拽事件執行,1秒內調用屢次DragFn函數。
// 實現效果:若是1秒內執行了屢次DragFn函數,那麼DragFn函數1秒只能執行一次(5s執行5次)。
(function(){
  const box_dom  = document.getElementsByClassName('box')[0];
  let isDrag = false; //拖拽狀態
  let drag_position = {}; //記錄開始拖拽時元素座標
  
  // 開始拖拽
  // clientX/clientY - 鼠標指針的水平/垂直座標
  box_dom.addEventListener('dragstart',function(e){
    if(e.target === box_dom){
      isDrag = true;
      //getBoundingClientRect方法返回元素的大小及其相對於視口的位置
      let {left,top} = box_dom.getBoundingClientRect(); 
      drag_position.left = e.clientX - left;
      drag_position.top = e.clientY - top;
    }
  
  },false)
  
  const DragFn = throttle(Fn,1000);
  // 拖拽移動
  box_dom.addEventListener('drag',DragFn,false);
  // 拖拽結束
  box_dom.addEventListener('dragend',function(e){
    isDrag = false;
  },false)
  
  function throttle(fn,timer){
    let init_time = 0;
    // 回調函數提供給drag事件
    return function(...args){
      let now_time = +new Date();
      if(now_time-init_time > timer){
        init_time = now_time;
        fn.apply(this,args);
      }
    }
  }
  // 節流執行的函數
  function Fn(e){
    e.preventDefault();
    if(isDrag&&e.clientX!==0){
      let t_left = e.clientX - drag_position.left;
      let t_top = e.clientY - drag_position.top;
      box_dom.style.left = t_left+'px';
      box_dom.style.top = t_top+'px';

      const timer = new Date();
      console.log(`${timer.getMinutes()}${timer.getSeconds()} ---------- Drag Dom----------`);
    }
  }
})()
複製代碼

2、函數防抖(debounce)

input若是2秒以內繼續輸入內容,那麼計時器從新回到2秒,函數不執行(回表),等待輸入完成2秒時間到後執行函數。app

  • 做用:例如經過監聽input keydown事件,請求搜索內容,爲了不過於頻繁的執行請求,須要使用函數防抖來實現優化。

  • search.js - 示例code
"use strict";
// 函數防抖(debounce) - 情景:當input輸入內容時,像後臺請求搜索內容。
// 實現效果:若是2秒以內從新輸入,那麼計時器從新回到2秒函數不執行(回表),等待輸入完成2秒時間到後執行函數。

(function(){
  const SeachDom = document.getElementsByTagName('input')[0];

  const KeyDownFn = debounce(Fn,2000);
  SeachDom.addEventListener('keydown',KeyDownFn);

  function debounce(fn,timer){
    let timer_out = null;

    return function(...args){
      // 清除計時器
      if(timer_out) clearTimeout(timer_out);

      timer_out = setTimeout(()=>{
        fn.apply(this,args);
      },timer)

    }
  }

  // 請求搜索內容操做
  function Fn(e){
    console.log(e.target.value, '<------search values');
  }

})();

複製代碼

3、HTML 代碼

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>函數防抖/節流Demo</title>
  <style> html,body{ width: 100%; height: 100%; padding:0; margin:0; } .box,.debounce{ width: 200px; height: 200px; background: skyblue; position: absolute; left: 20px; top: 20px; border-radius: 10px; } .debounce{ top: 300px; background: yellowgreen; line-height: 200px; text-align: center; padding: 0 20px; } .debounce input{ top: 300px; display: inline-block; height: 30px; width: 100%; font-size: 16px; padding-left: 10px; } .box{ cursor: move; } .box>p,.debounce>p{ margin: 0; display: flex; height: 100%; line-height: 30px; flex-direction: column; justify-content: center; align-items: center; color: #333; } </style>
</head>
<body>
  <section class="box" draggable="true">
    <p>
      <span>
        拖拽節流
      </span>
      <span>
          (1秒移動一次)
      </span>
    </p>
    

  </section>
  <section class="debounce">
    <p>
      <input type="text" placeholder="搜索防抖" class="search-input">
      <br/>
      <span>
        輸入完成2秒後
      </span>
      <span>執行搜索請求</span>
    </p>
  </section>

  <!-- 拖拽 -->
  <script src='./src/drag.js'></script>
  <!-- 搜索 -->
  <script src='./src/search.js'></script>
</body>
</html>
複製代碼
相關文章
相關標籤/搜索