【Web前端開發】偷偷告訴你,我們項目里的進度條,全都是假的!
當前位置:點晴教程→知識管理交流
→『 技術文檔交流 』
導讀 這篇文章主要探討了項目中假進度條的實現。先介紹需求背景,然后調研了 NProgress 和 fake-progress 兩個方案,分析其源碼和特點。接著提到因現有方案的不足,作者萌生封裝自己的 hook(useFakeProgress)的想法,確定方案和入參,給出實現細節和示例,強調可根據業務定制。 扯皮最近接到了一個需求:前端點擊按鈕觸發某個任務并開啟輪詢獲取任務進度,直至 100% 任務完成后給予用戶提示 這個業務場景還挺常見的,但是突然上周后端聯系到我說現在的效果有點差,之前都是小任務那進度條展示還挺不錯的,現在有了一些大任務且會存在排隊阻塞的情況,就導致視圖上經常卡 0% 排隊,用戶體驗太差了,問能不能在剛開始的時候做個假進度先讓進度條跑起來?? 因此就有了這篇文章,簡單做一下技術調研以及在項目中的應用 正文其實假進度條也不難做,無非是輪詢的時候我們自己做一個隨機的自增,讓它卡到 99% 等待后端真實進度完成后再結束 只不過還是想調研一下看看市面上有沒有一些成熟的方案并去扒一下它們的源碼?? NProgress首先當我聽到這里的需求后第一時間想到的就是它:rstacruz/nprogress: For slim progress bars like on YouTube, Medium, etc 記得大學期間做的一些中后臺系統基本都少不了路由跳轉時的頂部進度條加載,那時候就有了解到 NProgress,它的使用方式也很簡單,完全手控:NProgress: slim progress bars in JavaScript,去文檔里玩一下就知道了 視圖呈現的效果就是如果你不手動結束那它就會一直緩慢前進卡死 99% ,挺符合我們這里的需求,可以去扒一下它內部進度計算相關的邏輯 NProgress 的內容實際上比較少,源碼拉下來可以看到主要都在這一個 JS 文件里了: 需要注意的是我們看的是這個版本:rstacruz/nprogress at v0.2.0,master 分支與 npm 安裝的 0.2.0 內部實現還是有些差別的 我們這里不關注它的樣式相關計算,主要來看看對進度的控制,直奔 start 方法: 還是比較清晰的,這里的 set 方法里有一大堆設置動畫樣式邏輯都被我剪掉了,關于進度相關的只有這些。相當于利用 clamp 來做一個夾層,因為初始進來的 n 為 null,所以經過處理后進度變為 0.08 再回到 start 的邏輯,其中 看來這里就是進度控制的核心邏輯了, 而在 最后再調用 當然
即根據當前進度 n 計算剩余進度,再隨機生成自增值 再來看 按理來說直接將進度設置為 1 就行,但它以鏈式調用 而這里 一句話總結一下 NProgress 的進度計算邏輯:隨機值自增,最大值限制 但是因為 NProgress 與進度條樣式強綁定,我們肯定是沒法直接用的 fake-progress至于 fake-progress 則是我在調研期間直接搜關鍵詞搜出來的??:piercus/fake-progress: Fake a progress bar using an exponential progress function 很明顯看介紹就是干這個事的,而且還十分專業,引入數學函數展示假進度條效果,具有說服力: 所以我們項目中其實就是用的這個包,只不過和 NProgress 類似,兩個包都比較老了,瞟一眼源碼發現都是老 ES5 了?? 因為我們項目中用的是 React,這里給出 React 的 demo 吧,為了編寫方便使用了幾個 ahooks 里的 hook: 其實使用方法上與 NProgress 都類似,不過兩者都屬于通用的工具庫不依賴其他框架,所以像視圖渲染都需要自己手動來做 注意實例化中的傳參 因為不涉及到樣式,fake-progress 源碼更簡單,核心就在這里: 下方的數學公式就是介紹圖中展示的,只能說剛看到這部分內容是真的是死去的數學只是突然又開始攻擊我??,寫了那么多函數,數學函數是啥都快忘了 我們來簡單分析一下這個函數 那假如這里改成 exp(-x) 呢?有那味了,以前應該是有一個類似的公式 與 圖像效果是關于 y 軸對稱,好像是有些特殊的不符合這個規律???反正大部分都是滿足的 OK,那我們繼續進行轉換,看看 -exp(-x) 的效果 同樣有個公式 與 圖像效果是關于 x 軸對稱: 初見端倪,不知道你們有沒有注意 -exp(-x) 最終呈現的圖像是無限接近于 x 軸的,也就是 0: 那有了??,假如我再給它加個 1 呢?它不就無限接近于 1 了,即 -exp(-x) + 1,這其實就是 fake-progress 里公式的由來: 但你會發現如果 x 按 1 遞增就很快進度就接近于 1 了,所以有了
所以 fake-progress 的核心原理是借助數學函數,以函數值無限接近于 1 來實現假進度條,但是這種實現有一個 bug,可以看我提的這個 issues,不過看這個包的更新時間感覺作者也不會管了??: bug: progress may reach 100% · Issue #7 · piercus/fake-progress useFakeProgress雖然我們現在項目中使用的是 fake-progress,但是個人感覺用起來十分雞肋,而且上面的 bug 也需要自己手動兼容,因此萌生出自己封裝一個 hook 的想法,讓它更符合業務場景 首先我們確定一下進度計算方案,這里我毫不猶豫選擇的是 NProgress 隨機值增長方案,為什么?因為方便用戶自定義 而且 NProgress 相比于 fake-progress 有一個巨大優勢:手動 set 進度后仍然保持進度正常自動遞增 這點在 fake-progress 中實現是比較困難的,因為你無法保證手動 set 的進度是在這個函數曲線上,相當于給出函數 y 值反推 x 值,根據反推的 x 值再進行遞增,想想都麻煩 確定好方案后我們來看下入參吧,參考 NProgress 我定義了這幾個配置項: 這里我簡單解釋一下 rerender 和 amount 配置: 實際上在封裝這個 hook 的時候我一直在糾結這里的 progress 到底是 state 還是 ref,因為大多數場景下 hook 內部通過輪詢定時器更新進度,而真實業務代碼中也會開啟定時器去輪詢監聽業務接口的 所以如果寫死為 state,那這個場景 hook 內部的每次更新 render 是沒必要的,但是假如用戶又想只是使用假進度展示,沒有后端業務接口呢? 思來想去其實完全可以放權給用戶進行配置,因為 state = ref + update,統一使用 ref,用戶配置 rerender 時我們在每次更新時 update 即可 至于 amount 我是希望放權給用戶進行自定義遞增值,你可以配置成一個固定值也可以配置成隨機值,更可以像 NProgress master 分支下這樣根據當前進度來控制自增,反正以函數參數的形式能夠拿到當前的 progress: 至于實現細節就不再講述了,實際上就是輪詢定時器沒什么復雜的東西,直接上源碼了:
這里需要補充一個細節,在返回值里使用的是 progressDataRef 是 formatter 后的結果為 string 類型,如果用戶想要獲取原 number 的 progress,可以使用最下面提供的 get 方法拿 progressRef 值 一個 demo 看看效果,感覺還可以: 當然由于直接返回了 ref,為了防止用戶篡改可以再上一層代理劫持,我們就省略了 這也算一個工具偏業務的 hook,可以根據自己的業務來進行定制,這里很多細節都沒有補充只是一個示例罷了?? End以上就是這篇文章的內容,記得上班之前還在想哪有那么多業務場景需要封裝自定義 hook,現在發現真的是各種奇葩需求都可以封裝,也算是豐富自己武器庫了... 作者:討厭吃香菜 鏈接:https://juejin.cn/post/7449307011710894080 來源:稀土掘金 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。 該文章在 2025/1/10 15:08:28 編輯過 |
關鍵字查詢
相關文章
正在查詢... |