官术网_书友最值得收藏!

2.5.5 history.block原理解析

history.block對應history v3.x中的listenBefore監聽方法,history.block同時也服務于React Router的Prompt組件。在2.1節曾介紹過,history.block的目的是在一些表單還未輸入完成的頁面,對用戶的意圖跳轉行為進行阻止或彈窗確認。

那么history.block是如何“攔截”瀏覽器導航的呢?以browserHistory為例,對于history.push和history.replace方法,其會在真正跳轉前調用transitionManager.confirmTransitionTo 進行跳轉確認,各類history都會在內部創建transitionManager:

transitionManager.confirmTransitionTo的主要作用是確認是否應該阻止跳轉,其實現如下:

而history.block的真正作用是設置confirmTransitionTo中的prompt函數:

所以,在執行block后,prompt變量不為null。這樣在使用history每次調用history.push、history.replace時,將檢查prompt,因為prompt不為null將進行跳轉攔截。但如果調用history.go或者單擊瀏覽器的“前進”或“后退”按鈕跳轉該如何“攔截”?事實上,單擊“前進”或“后退”按鈕只能監聽到popstate、hashchange事件,但是此刻瀏覽器地址已經改變了,所以為了“攔截”跳轉,要做的是在地址發生變化后進行人工恢復。在此情況下,可調用revertPop進行地址恢復:

地址恢復的依據是2.5.2節介紹過的內存棧。根據內存棧(如browserHistory的allKeys)、已經發生跳轉的地址,以及希望恢復的地址三部分信息,可以計算出恢復到目標地址所需的跳轉恢復變量delta值。

在browser路徑下,進行人工恢復會觸發兩次popstate事件,第一次在單擊瀏覽器的“后退”或“前進”按鈕時觸發,第二次在調用history.go方法時觸發。第一次觸發popstate事件不會通知history.listen監聽器,只有第二次觸發popstate事件后在使用history.go恢復地址時,才會重新觸發一次history.listen監聽器,并觸發一次渲染??雌饋砺窂绞遣蛔兊?,原路徑對應的組件會接受一次props更新。

主站蜘蛛池模板: 金昌市| 会同县| 邓州市| 西乡县| 湟中县| 玛沁县| 西安市| 边坝县| 德庆县| 赤水市| 中阳县| 客服| 景东| 益阳市| 光泽县| 英超| 泰宁县| 吕梁市| 旌德县| 合阳县| 东台市| 都匀市| 布尔津县| 易门县| 沅江市| 九龙县| 三原县| 理塘县| 堆龙德庆县| 昂仁县| 长子县| 涟水县| 广昌县| 沅江市| 广水市| 潞西市| 渝中区| 黔南| 双江| 双柏县| 仁寿县|