在之前的文章(標記本次瀏覽的第一個頁面)中提到vue-router會在history.state
中存放一個字符串來標識路由,這一點在文檔中沒有明說它的原理,我們在利用history.state
來標記第一層路由的時候需要對vue-router的這一數據進行特殊的處理。
vue-router@4
但是在新的vue-router@4中,我們不需要對history.state
進行特殊的處理,反而可以利用vue-router存放在其中的數據來標記第一層路由。
在vue-router@4的文檔中有這樣一段描述(history.state的用法)
Vue Router 將信息保存在 history.state 上。如果你有任何手動調用 history.pushState() 的代碼,你應該避免它,或者用的 router.push() 和 history.replaceState() 進行重構。原因:我們使用歷史狀態來保存導航信息,如滾動位置,以前的地址等。
也就是是說vue-router@4明確的說明了,路由信息是保存在history.state中的。
history.state
我們用vue-cli創建一個vue@3的項目來看一個例子,如果我們直接打開網址(比如從VSCode的控制檯按Ctrl進入http://localhost:8080),在瀏覽器的控制檯打印history.state
,可以看到輸出爲:
{
back: null
current: "/"
forward: null
position: 0
replaced: true
scroll: null
}
這些就是vue-router存放的路由信息,其中:
- back:上一層路由地址
- current:當前路由地址
- forward:下一層路由地址
- position:當前路由在歷史記錄中的位置
- replaced:是否是替換路由
- scroll:頁面位置信息
在源碼中其類型被定義爲:
interface StateEntry extends HistoryState {
back: HistoryLocation | null
current: HistoryLocation
forward: HistoryLocation | null
position: number
replaced: boolean
scroll: _ScrollPositionNormalized | null | false
}
且我們可以看到它是這樣被初始化的:
{
back: null,
current: currentLocation.value,
forward: null,
// the length is off by one, we need to decrease it
position: history.length - 1,
replaced: true,
// don't add a scroll as the user may have an anchor and we want
// scrollBehavior to be triggered without a saved position
scroll: null,
}
也就是說position
是當前路由歷史長度減一,如果這是瀏覽器打開的第一個頁面,路由歷史長度爲1,那麼當前路由位置就是0。以此我們可以判斷這是進入頁面的第一層路由。
當position
不爲0的時候,比如先打開瀏覽器,在輸入http://localhost:8080時,由於瀏覽器初始頁面也算是一層路由,position
就爲1。
{
back: null
current: "/"
forward: "/about"
position: 1
replaced: true
scroll: {left: 0, top: 0}
}
此時我們可以通過判斷back
是否爲null來判斷是否是第一層路由。因爲vue-router隨他可以取得瀏覽器歷史的位置,但無法獲取其他頁面的路徑。而在自身的路由體系內,路徑都是可以拿到的。因爲,back === null
就以爲這當前處於這個SPA的第一層路由。
總結
在vue-router@4中,我們可以通過:
window.history.state.position === 0 || window.history.state.back === null
來判斷當前路由是否是本次SPA瀏覽的第一層路由。