前端工程師們都聽過看起來很高級的詞,節流和防抖,其實節流就是throttle,防抖就是debounce,其實這個也屬於前端性能優化的一部分。前端
在作遠程搜索時,若是每輸入1個字就調用1次接口,就會頻繁查詢數據庫,假設咱們的查詢是"12345",不考慮用戶輸入錯誤的狀況,至少會請求5次。vue
再思考一個問題,按鈕的click重複觸發(例如快速點擊2次,3次,...n次)該如何在前端作一層攔截,避免發送重複請求到服務端,最多見的是新增時插入重複數據,這個問題該怎麼辦呢?git
<template> <input @input="handleInput"/> </template> <script> export default { name: 'input', data() { return { delay: 1000, count: 0, }; }, methods: { handleInput(e) { console.log(`debounce wait時間爲${this.delay}ms`); console.log('觸發了input事件', e.target.value); this.count++; console.log(`觸發了${this.count}次遠程搜索`); }, }, }; </script>
打印結果:
debounce wait時間爲1000ms
觸發了input事件 1
觸發了1次遠程搜索
debounce wait時間爲1000ms
觸發了input事件 12
觸發了2次遠程搜索
debounce wait時間爲1000ms
觸發了input事件 123
觸發了3次遠程搜索
debounce wait時間爲1000ms
觸發了input事件 1234
觸發了4次遠程搜索
debounce wait時間爲1000ms
觸發了input事件 12345
觸發了5次遠程搜索github
說明:輸入5個數查詢5次,形成了頻繁查詢數據庫的行爲,是一種性能浪費。數據庫
有,能夠爲函數設置一個setTimeout函數,至關於定時調用接口,這種方法是低效的,也是很是愚蠢的,須要控制開關定時器,一旦搜索功能多了,就更蠢了。canvas
有,debounce(防抖)就是作這個事情的,lodash從0.1.0就支持了這個方法。segmentfault
<template> <input @input="debounceHandleInput"/> </template> <script> import _ from 'lodash'; export default { name: 'input-debounce', data() { return { delay: 1000, }; }, computed: { debounceHandleInput() { return _.debounce(this.handleInput, this.delay); }, }, methods: { handleInput(e) { console.log(`debounce wait時間爲${this.delay}ms`); console.log('觸發了input事件', e.target.value); this.count++; console.log(`觸發了${this.count}次遠程搜索`); }, }, }; </script>
打印結果:
debounce wait時間爲1000ms
觸發了input事件 12345後端
說明:在1000ms時間範圍內觸發,僅僅觸發了一次遠程搜索,也就是僅僅調用一次後端接口,達到咱們的預期效果。性能優化
<template> <input @input="throttleHandleInput"/> </template> <script> import _ from 'lodash'; export default { name: 'input-throttle', data() { return { delay: 1000, count: 0, }; }, computed: { throttleHandleInput() { return _.throttle(this.handleInput, this.delay); }, }, methods: { handleInput(e) { console.log(`throttle wait時間爲${this.delay}ms`); console.log('觸發了input事件', e.target.value); this.count++; console.log(`觸發了${this.count}次遠程搜索`); }, }, }; </script>
打印結果:
throttle wait時間爲1000ms
觸發了input事件 1
觸發了1次遠程搜索
throttle wait時間爲1000ms
觸發了input事件 12345微信
說明:在1000ms時間範圍內觸發,僅僅觸發了2次遠程搜索,調用2次後端接口。用戶首次輸入1當即返回數據,保證數據到達速度,也提高了用戶體驗。中間的12,123,1234被節流函數成功攔截避免觸發。而12345是咱們最終須要的搜索結果,在最後返回給用戶。達到咱們的預期效果。
<template> <button @click="handleClick">新增</button> </template> <script> export default { name: 'click', data() { return { count: 0, }; }, methods: { handleClick(e) { console.log('觸發了click事件', e.target.value); this.count++; console.log(`觸發了${this.count}次新增數據`); }, }, }; </script>
觸發了click事件
觸發了1次新增數據
觸發了click事件
觸發了2次新增數據
說明:快速點擊2次「新增」按鈕,而最終只觸發了2次數據新增,形成重複數據插入。
<template> <button @click="debounceHandleClick">新增</button> </template> <script> import _ from 'lodash'; export default { name: 'click-debounce', data() { return { delay: 1000, count: 0, }; }, computed: { debounceHandleClick() { return _.debounce(this.handleClick, this.delay); }, }, methods: { handleClick(e) { console.log(`debounce wait時間爲${this.delay}ms`); console.log('觸發了click事件', e.target.value); this.count++; console.log(`觸發了${this.count}次新增數據`); }, }, }; </script>
打印結果:
debounce wait時間爲1000ms
觸發了click事件
觸發了1次新增數據
說明:快速點擊2次「新增」按鈕,而最終只觸發了1次數據新增,達到了咱們的預期效果。
loading是指在異步請求完成(成功或者失敗)前,開啓loading,使得按鈕或者用戶界面處於「加載中」「轉圈」「spin"這樣的一個狀態,從而禁止用戶發起重複操做,異步請求完成後,關閉loading。
<template> <Button @click="loadingHandleClick" :loading="loading">新增</Button> </template> <script> export default { name: 'click-loading', data() { return { loading: false, count: 0, }; }, methods: { loadingHandleClick(e) { this.loading = true; this.count++; console.log(`觸發了${this.count}次新增數據`); console.log('發起異步請求,loding爲:', this.loading); setTimeout(() => { console.log('異步請求執行了1s'); this.loading = false; console.log('異步請求完成,loding爲:', this.loading); }, 1000); }, }, }; </script>
觸發了1次新增數據
發起異步請求,loding爲: true
異步請求執行了1s
異步請求完成,loding爲: false
說明:第1次事件觸發後,按鈕處於loading爲true狀態,禁止用戶觸發,1秒後異步請求執行完成,loading爲false,容許用戶再次使用。所以都沒法作到快速點擊2次「新增」按鈕,只能觸發1次,重複的第2次觸發用戶沒法觸發,最終只觸發了1次數據新增,達到了咱們的預期效果。
地址:http://demo.nimius.net/deboun...
圖片:
經過在canvas上連續觸發mousemove事件咱們發現:
期待和你們交流,共同進步,歡迎你們加入我建立的與前端開發密切相關的技術討論小組:
- SegmentFault技術圈:ES新規範語法糖
- SegmentFault專欄:趁你還年輕,作個優秀的前端工程師
- 知乎專欄:趁你還年輕,作個優秀的前端工程師
- Github博客: 趁你還年輕233的我的博客
- 前端開發QQ羣:660634678
- 微信公衆號: 人獸鬼 / excellent_developers
努力成爲優秀前端工程師!