首頁 > web前端 > Vue.js > 主體

淺析Vue組件中如何使用 防手震 和 節流

青灯夜游
發布: 2021-11-25 19:41:39
轉載
2719 人瀏覽過

Vue元件中如何使用 防手震 和 節流?以下這篇文章透過範例帶大家了解Vue元件中使用 防手震 和 節流 控制 觀察者和事件處理程序的方法,希望對大家有幫助!

淺析Vue組件中如何使用 防手震 和 節流

在監聽頻繁觸發的事件時,一定要多加小心,例如 使用者在輸入框打字、視窗大小調整、捲動、Intersection Observer 事件。

這些事件總是會被頻繁觸發,可能 幾秒一次。如果針對每次事件都發起 fetch 請求(或類似的行為),那顯然是不明智的。

我們需要做的就是減緩事件處理程序的執行速度。這種緩衝技巧就是 防手震(debounce) 和 節流(throttle)

在本文中,你會了解如何在 Vue 元件中 使用 防手震 和 節流 控制 觀察者(watchers) 和 事件處理程序。 【相關推薦:《vue.js教學》】

1. 觀察者防手震

我們先從一個簡單的元件開始,我們的任務就是將用戶輸入到文字方塊中的文字輸出到控制台:

<template>
  <input v-model="value" type="text" />
  <p>{{ value }}</p>
</template>
<script>
export default {
  data() {
    return {
      value: "",
    };
  },
  watch: {
    value(newValue, oldValue) {
      console.log("Value changed: ", newValue);
    }
  }
};
</script>
登入後複製

#開啟demo:

https://codesandbox.io/s/vue-input-szgn1?file=/ src/App.vue

開啟demo,在輸入框中敲幾個字元。每次輸入時,數值就會被 log 到控制台。

我們透過使用 觀察者(watcher) 監聽 value 資料屬性 來實現了列印日誌。但如果你想在 觀察者的回呼 中加入一個 使用 value 作為參數 的 GET 請求,那你應該不會期望太過頻繁地發起請求。

我們來對 列印控制台日誌 這個行為做一下 防手震。核心思想是建立一個 防手震函數,然後在 觀察者 內部呼叫該函數。

我在這裡選擇了 'lodash.debounce' 的 防手震實現,但你可以自由選擇喜歡的實現方式。

我們將防手震邏輯套用到元件:

<template>
  <input v-model="value" type="text" />
  <p>{{ value }}</p>
</template>
<script>
import debounce from "lodash.debounce";
export default {
  data() {
    return {
      value: "",
    };
  },
  watch: {
    value(...args) {
      this.debouncedWatch(...args);
    },
  },
  created() {
    this.debouncedWatch = debounce((newValue, oldValue) => {
      console.log(&#39;New value:&#39;, newValue);
    }, 500);
  },
  beforeUnmount() {
    this.debouncedWatch.cancel();
  },
};
</script>
登入後複製

試試demo

https://codesandbox.io/s/vue-input-debounced -4vwex?file=/src/App.vue

如果你打開這個demo,你會發現其實從使用者角度來看,變化不大:你依舊可以像上一個demo 中一樣自由輸入字元。

但有一個差異:只有在最後一次輸入的 500ms 之後,才會將新的輸入值列印日誌到控制台。這說明 防手震 在生效。

觀察者的防手震實作只需要3 個簡單步驟:

  • create() 鉤子裡,建立防手震回調,並將其賦值到實例上:this.debouncedWatch = debounce(..., 500)

  • 在觀察者回呼watch.value() { ... }#  中傳入正確的參數呼叫this.debouncedWatch()

  • 最後,beforeUnmount() 鉤子中呼叫this.debouncedWatch.cancel() ,在卸載元件之前,取消所有還在pending的防抖函數執行。

採用同樣的方式,你可以對任意資料屬性的 觀察者 應用 防手震。然後就可以安全執行 防手震回調內部的一些比較重的操作,例如 網路請求、繁重的 DOM 操作,等等。

2. 事件處理器 防手震

上面一節,我展示如何對 觀察者 使用 防手震,那麼常規的事件處理器呢?

我們重複使用先前使用者輸入資料到輸入框的例子,但這次會為輸入框加個 事件處理器。

像往常一樣,如果你沒有採取任何緩衝的措施,每當值被修改時,會被印到控制台:

<template>
  <input v-on:input="handler" type="text" />
</template>
<script>
export default {
  methods: {
    handler(event) {
      console.log(&#39;New value:&#39;, event.target.value);
    }
  }
};
</script>
登入後複製

試試demo:

https://codesandbox.io/s/vue-event-handler-plls4?file=/src/App.vue

開啟這個demo,在輸入框中打幾個字元。看看控制台:你會發現每次你輸入的時候就會有日誌被印出來。

同樣,如果你會執行一些比較重的操作(例如網路請求),可就不合適了。

對事件處理器使用防手震,可以參考下面這個:

<template>
  <input v-on:input="debouncedHandler" type="text" />
</template>
<script>
import debounce from "lodash.debounce";
export default {
  created() {
    this.debouncedHandler = debounce(event => {
      console.log(&#39;New value:&#39;, event.target.value);
    }, 500);
  },
  beforeUnmount() {
    this.debouncedHandler.cancel();
  }
};
</script>
登入後複製

試試看demo:

https://codesandbox.io/s/vue -event-handler-debounced-973vn?file=/src/App.vue

#開啟demo,輸入一些字元。元件只有在最後一次輸入的 500ms 之後,才會將新的輸入值列印日誌到控制台。防抖 再一次生效了!

事件處理器的防手震實作只需要3 個步驟:

  • .在create() 鉤子裡,建立實例後,立刻將防抖回呼debounce(event => {...}, 500) 賦值到this.debouncedHandler

  • 在输入框的 template 中 给 v-on:input 赋上 debouncedHandler<input v-on:input="debouncedHandler" type="text" />

  • 最后,在卸载组件之前, 在 beforeUnmount() 钩子中 调用 this.debouncedHandler.cancel() ,取消所有还在 pending 的 函数调用。

另一方面,这些例子应用了 防抖 的技术。然而,同样的方式可以以用于创建 节流函数。

3. 注意

你可能不理解:为什么不直接在 组件的 method 选项中创建 防抖函数,然后在 template 中调用这些方法作为事件处理器?

// ...
  methods: {
    // Why not?
    debouncedHandler: debounce(function () { ... }}, 500)
  }
// ...
登入後複製

这比在实例对象上创建 防抖函数 要简单的多。

例如:

<template>
  <input v-on:input="debouncedHandler" type="text" />
</template>
<script>
import debounce from "lodash.debounce";
export default {
  methods: {
    // Don&#39;t do this!
    debouncedHandler: debounce(function(event) {
      console.log(&#39;New value:&#39;, event.target.value);
    }, 500)
  }
};
</script>
登入後複製

试试 demo

https://codesandbox.io/s/vue-event-handler-debounced-incorrectly-320ci?file=/src/App.vue

这次不是在 created() 钩子 里创建 防抖回调了,而是将 防抖回调 赋给了 methods.debouncedHandler

你如果试过 demo,你会发现是有效果的!

问题是,组件使用 export default { ... } 导出的 options 对象,包括方法,会被组件实例重用。

如果网页中有 2 个以上的组件实例,那么所有的组件都会应用 相同 的防抖函数 methods.debouncedHandler — 这会导致防抖出现故障。

4. 总结

在 Vue 中,可以很轻松的对 观察者 和 事件处理器 应用 防抖 和 节流。

核心逻辑就是,在 created() 钩子 里,创建 防抖 或 节流 的回调,并赋值在实例上。

// ...
  created() {
    this.debouncedCallback = debounce((...args) => {
      // The debounced callback
    }, 500);
  },
// ...
登入後複製

A)然后在观察者内部调用实例上的防抖函数:

// ...
  watch: {
    value(...args) {
      this.debouncedCallback(...args);
    },
  },
// ...
登入後複製

B)或在 template 中设定一个事件处理器:

<template>
  <input v-on:input="debouncedHandler" type="text" />
</template>
登入後複製

在这之后,每次调用 this.debouncedCallback(...args) ,就算执行频率非常高,内部的回调也能缓冲执行。

你对 Vue 中的 防抖 和 节流 还什么问题吗?欢迎提问!

更多编程相关知识,请访问:编程入门!!

以上是淺析Vue組件中如何使用 防手震 和 節流的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:juejin.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板