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