中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript中如何實現防抖和節流

發布時間:2021-09-28 09:15:37 來源:億速云 閱讀:150 作者:小新 欄目:開發技術

這篇文章主要為大家展示了“JavaScript中如何實現防抖和節流”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“JavaScript中如何實現防抖和節流”這篇文章吧。

防抖

自動門感應到有人,打開門,并且開始5秒倒計時,在 5 s 內有另外一個人靠近到門,門感應到人,重新5秒倒計時

當事件被觸發時,設定一個延遲,若期間事件又被觸發,則重新設定延遲,直到延遲結束,執行動作 (防止多次觸發)

web 應用上面

  • 改變頁面大小的統計

  • 滾動頁面位置的統計

  • 輸入框連續輸入的請求次數控制

一開始,點擊按鈕,console.log('pay money')

<body>
  <button id="btn">click</button>
</body>
<script>
  const btn = document.getElementById('btn')
  function payMoney() {
    console.log('pay money');
  }
  btn.addEventListener('click', payMoney)
</script>

定義 debounce

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
}
function debounce(func) {
  // 在函數里面返回函數 , 只有當點擊的時候才返回該函數
  return function () {
    func()
  }
}
btn.addEventListener('click', debounce(payMoney))

設置延時

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
}
function debounce(func, delay) {
  return function () {
    setTimeout(_ => func(), delay)
  }
}
btn.addEventListener('click', debounce(payMoney, 1000))

清除延時:未能執行

原因

每次點擊的時候就會執行返回函數里面的內容

每次點擊的執行函數都是獨立的,互不干涉

正因為他們之間沒有聯系,清除延時在這里完全沒有起作用

要讓這些獨立的執行函數之間有聯系,需要用到作用域鏈(閉包)

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
}
function debounce(func, delay) {
  return function () {
    let timer
    clearInterval(timer)
    timer = setTimeout(_ => func(), delay)
  }
}
btn.addEventListener('click', debounce(payMoney, 1000))

將 timer 放在返回函數的外圍,這樣在定義監聽事件的同時,就定義了 timer變量

因為作用域鏈,所有獨立的執行函數都能訪問到這個timer變量

而且現在這個timer變量只創建了一次。是唯一的,我們只不過不斷給timer賦值進行延時而已

每個清除延時就是清除上一個定義的延時,相當于多個函數共用同一個外部變量

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
}
function debounce(func, delay) {
  let timer
  return function () {
    clearInterval(timer)
    timer = setTimeout(_ => func(), delay)
  }
}
btn.addEventListener('click', debounce(payMoney, 1000))

此時的代碼,this 是指向 window ?

因為回調的原因,運行時已經在Window下了

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
  console.log(this);
}
function debounce(func, delay) {
  let timer
  return function () {
    clearInterval(timer)
    timer = setTimeout(_ => func(), delay)
  }
}
btn.addEventListener('click', debounce(payMoney, 1000))

解決辦法

在 setTimeout 之前將 this 保存下來,此時的 this 是指向按鈕的

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
  console.log(this);
}
function debounce(func, delay) {
  let timer
  // 只有當點擊的時候,才返回此函數,所以 this 是指向按鈕的
  return function () {
    let context = this
    clearInterval(timer)
    timer = setTimeout(_ => {
      func.apply(context)
    }, delay)
  }
}
btn.addEventListener('click', debounce(payMoney, 1000))

考慮參數的問題,添加 arg

const btn = document.getElementById('btn')
function payMoney() {
  console.log('pay money');
  console.log(this);
}
function debounce(func, delay) {
  let timer
  return function () {
    let context = this
    let args = arguments
    clearInterval(timer)
    timer = setTimeout(_ => {
      func.apply(context)
      console.log(context, args);
    }, delay)
  }
}
btn.addEventListener('click', debounce(payMoney, 1000))

節流

先觸發一次后,防止接下來多次觸發

滾動屏幕:統計用戶滾動屏幕的行為來作出相應的網頁反應

當用戶不斷進行滾動,就會不斷產生請求,相應也會不斷增加,容易導致 ?? 網絡阻塞

我們就可以在觸發事件的時候就馬上執行任務,然后設定時間間隔限制,在這段時間內不管用戶如何進行滾動都忽視操作

在時間到了以后如果監測到用戶有滾動行為,再次執行任務。并且設置時間聞隔

首先,寫個改變頁面尺寸的同時改變頁面背景顏色的代碼

function coloring() {
  let r = Math.floor(Math.random() * 255)
  let g = Math.floor(Math.random() * 255)
  let b = Math.floor(Math.random() * 255)
  document.body.style.background = `rgb(${r}, ${g}, ${b})`
}
window.addEventListener('resize', coloring)
function throttle(func, delay) {
  let timer
  return function () {
    timer = setTimeout(_ => {
      func()
    }, delay)
  }
}
window.addEventListener('resize', throttle(coloring, 2000))

判斷觸發的事件是否在時間間隔內

  • 不在:觸發事件

  • 在:不觸發事件

function throttle(func, delay) {
  let timer
  return function () {
    // timer 被賦值了,直接返回,即不執行任務
    if (timer) {
      return
    }
    // 此時 timer 沒被賦值,或 timer 已經執行完了  
    // 為 timer 賦值進行延時執行
    timer = setTimeout(_ => {
      func()
      // 延遲執行以后我們要清空timer的值
      timer = null
    }, delay)
  }
}
window.addEventListener('resize', throttle(coloring, 2000))

解決 this 指向(雖然當前的這個例子就是在 Window 下的)

function throttle(func, delay) {
  let timer
  return function () {
    let context = this
    let args = arguments
    // timer 被賦值了,直接返回,即不執行任務
    if (timer) {
      return
    }
    // 此時 timer 沒被賦值,或 timer 已經執行完了  
    // 為 timer 賦值進行延時執行
    timer = setTimeout(_ => {
      func.apply(context, args)
      // 延遲執行以后我們要清空timer的值
      timer = null
    }, delay)
  }
}
window.addEventListener('resize', throttle(coloring, 1000))

節流核心:事件間隔 另一種常見的時間間隔就是用Date對象

function throttle(func, delay) {
  // 我們要和前一個時間點進行比較才能確定是否已經過了時間間隔
  // 在返回函數外圍,避免每次執行都被自動修改
  let pre = 0
  return function () {
    // 保存執行函數當時的時間
    let now = new Date()
    // 剛開始,一定會執行
    if (now - pre > delay) {
      // 已經過了時間間隔,就可以執行函數了
      func()
      // 執行后,重新設置間隔點
      pre = now
    }
  }
}
window.addEventListener('resize', throttle(coloring, 1000))

解決參數問題

function throttle(func, delay) {
  let pre = 0
  return function () {
    let context = this
    let args = arguments
    let now = new Date()
    if (now - pre > delay) {
      func.apply(context, args)
      pre = now
    }
  }
}
window.addEventListener('resize', throttle(coloring, 1000))

以上是“JavaScript中如何實現防抖和節流”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

读书| 天峻县| 平江县| 武川县| 策勒县| 乐山市| 那曲县| 葫芦岛市| 平定县| 英山县| 塔河县| 筠连县| 西林县| 城步| 万载县| 小金县| 建昌县| 潜山县| 南江县| 毕节市| 平塘县| 广河县| 泸水县| 灵台县| 永平县| 平果县| 应城市| 连江县| 娱乐| 西和县| 黄石市| 安福县| 图木舒克市| 海门市| 天峻县| 荆门市| 平乡县| 隆安县| 大城县| 华宁县| 神池县|