- 深入理解React Router:從原理到實踐
- 李楊韜
- 1257字
- 2021-04-16 16:10:47
2.6 history庫限制
2.6.1 history.block的使用限制
值得一提的是,history.block存在以下幾個問題。
1.刷新頁面后歷史棧丟失
對于大多數情況,history.block都能很好地工作,但是如果刷新頁面,則原內存將丟失。以browserHistory為例,allKeys會重新初始化為空,原歷史棧記錄將全部清空,而瀏覽器自身的歷史棧記錄在刷新后是不會丟失的,這種跟瀏覽器行為不一致之處造成了問題。例如對于browserHistory,有/a、/b、/c頁面,從/a頁面開始,按如下路徑進行跳轉:/a→/b→/c;如果在/c頁面進行了history.block阻止,這時由于每次導航都在內存中維護了歷史棧記錄,知道整個歷史棧的情況,所以能在調用history.go(-1)后退一次后,browserHistory再重新調用history.go(1)前進一次,即一次“后退”再“前進”,進而恢復到/c,達到了路徑不變的效果。如果在/c頁面調用history.block后再刷新,即在內存中的歷史棧內容丟失之后,先調用history.block,再調用history.go(-1)或history.go(-2),或者單擊瀏覽器地址欄側的“后退”按鈕。這時由于內存中歷史棧被清空,沒有可供參考的回退歷史記錄,因此在內部計算得到的跳轉恢復變量delta值為0,這時雖然history.go(-1)或history.go(-2)已經生效,URL已經改變為/b或/a,但是URL地址并未如期恢復到/c,最終出現URL與頁面內容不一致的情況。
2.移動端的限制
如果遇到移動端歷史棧記錄數量的上限為100或者在移動端window.confirm不生效等問題,則需要Native開發者配合支持。比如在iOS12移動端場景下,history.block使用的默認prompt為window.confirm,其不會如PC頁面一樣有彈窗提示,而是默認返回“false”,這將阻止瀏覽器跳轉,而不是彈出提示框讓用戶進行確認。
3.hash路由問題
如果是hash路由,則有兩個問題,一個問題是使用path作為歷史棧記錄,path路徑與browserHistory的key作用一樣,但沒有使用key的原因是考慮到hash路由沒有window.history.state可以使用。所以該問題是路徑重復的問題,如棧中有兩個/b路徑,在尋找/b路徑時,將不知道以哪一個為準。例如當前棧路徑為/a→/b→/c→/b,如果此時在第一個/b頁面調用了history.block,再單擊瀏覽器的“后退”按鈕,強制返回到了/a,則要恢復到/b,這時將不知道恢復到哪個/b。history將會錯誤地恢復到最后一個/b頁面,與預期不符合。
另一個問題是可以在地址欄中手動更改hash進行一次入棧操作,而事實上由于手動更改hash沒有調用push方法,內存中的歷史棧不會感知到手動更改hash導致的入棧。若當前路徑為/a→/b→/c,且在/c處調用了history.block,如果此時在地址欄中輸入/b,則路徑將為/a→/b→/→/b,這時應該調用history.go(-1)恢復到/c,以達到阻止跳轉的目的。由于內存中的棧只有/a→/b→/c,history將錯誤地認為當前的/b(手動輸入的/b)為/a之后的/b,則要從/b恢復到/c,應該是從第二個/b前進一步到/c,因而會錯誤地調用history.go(1)進行恢復,而不是調用history.go(-1)。結果是路徑已經變為了/b(history判斷需要前進一步,但是此時已經是最后的位置),但是頁面還是/c的頁面(頁面被history.block所阻止)。
事實上,上述問題的本質在于history庫無能力真正“阻止”URL的改變,目前history v4.x將歷史棧保存在內存中,從而造成了種種問題。
注意,對于memoryHistory.block方法是可以放心使用的,因為路徑都在內存中進行了維護,可認為memoryHistory沒有瀏覽器這個“副作用”。由于其沒有瀏覽器的“后退”按鈕和對應的瀏覽器popstate等事件,所有的前進、后退動作都在內存中操作,所以如果進行了history.block操作,則無須進行如browserHistory、hashHistory中的地址恢復行為,僅需執行一次更新操作即可。
- PHP 7底層設計與源碼實現
- Hands-On JavaScript High Performance
- Data Analysis with IBM SPSS Statistics
- JavaScript前端開發與實例教程(微課視頻版)
- Python數據可視化之Matplotlib與Pyecharts實戰
- SQL基礎教程(視頻教學版)
- Learning Python by Building Games
- Visual Basic程序設計上機實驗教程
- Mastering Git
- Domain-Driven Design in PHP
- JavaScript應用開發實踐指南
- JavaScript動態網頁編程
- Angular應用程序開發指南
- 工業機器人離線編程
- DevOps 精要:業務視角