Chrome 105 針對 Navigation API 的 NavigateEvent
推出兩種新方法 (於 102 年推出),以改善實務上有問題的方法。intercept()
,可讓開發人員在導覽後控制狀態,取代難以使用的 transitionWhile()
。捲動至網址中指定的錨點的 scroll()
方法取代了不適用於所有導覽類型的 restoreScroll()
。
在這篇文章中,我會說明這兩種問題的問題,以及新方法如何解決這些問題。
NavigateEvent.transitionWhile()
在 Chrome 102 版中透過 Navigation API 引入的 NavigateEvent.trasitionWhile()
方法,會攔截單一頁面應用程式中的用戶端轉場效果。第一個引數是一個 promise 可讓瀏覽器和網頁應用程式的其他部分知道已完成。
實際運作成效不佳。請參考以下常見的編碼模式:
event.transitionWhile((async () => {
doSyncStuff();
await doAsyncStuff();
})());
這在功能上與下列程式碼相同。這會導致 API 的部分內容在 API 之前執行,但開發人員想要攔截導覽。
doSyncStuff();
event.transitionWhile((async () => {
await doAsyncStuff();
})());
舉例來說,這可能會令人忽略應用程式處於捲動還原邏輯,也就是在 DOM 改變 (而非之前) 擷取捲動位置。
異動情形
如要取代 transitionWhile()
,目前的規格導入了 NavigateEvent.intercept()
。除了 transitionWhile()
支援的 focusReset
和 scrollRestoration
屬性外,新方法會採用處理常式。新的處理常式一律會在導覽修訂後執行,且擷取捲動位置之類的項目,可避免 transitionWhile()
發生問題。
transitionWhile()
方法目前仍可使用,但已淘汰,並將在 Chrome 108 版中移除。
使用 Intercept()
NavigateEvent.intercept()
與 transitionWhile()
具有相同的限制,因為無法針對所有導覽事件呼叫。無法攔截跨來源導覽,也無法跨文件週遊。這樣做會擲回 "SecurityError"
類型的 DOMException
。
如要使用 intercept()
,只要在呼叫自訂處理常式時傳遞自訂處理常式即可。
navigation.addEventListener("navigate", event => {
event.intercept({
async handler() {
doSyncStuff();
await doAsyncStuff();
}
});
});
NavigateEvent.scroll()
瀏覽器可完全由瀏覽器處理 (例如從頁面頂端導覽到錨點 (從 /a
移至 /a#id
) 的導覽作業,即使在單一頁面應用程式中也能進行操作。但對於多頁面應用程式來說,前往其他「頁面」(/a
到 /b#id
) 的導覽操作較為簡單,對於單頁應用程式而言,則比較複雜。應用程式必須使用 NavigateEvent.transitionWhile()
攔截 /b#id
導覽,然後呼叫 NavigateEvent.restoreScroll()
以將錨點顯示在畫面上。如上所述,這目前仍很難達成。
異動情形
在單一頁面應用程式中,您現在可以控制瀏覽器是否處理捲動至錨點或程式碼的用途。
使用 Scroll()
根據預設,瀏覽器會在攔截器執行完畢之後,嘗試自動處理捲動。如要自行處理捲動,請將 scroll
設為 "manual"
,然後在瀏覽器嘗試設定捲動位置時呼叫 NavigateEvent.scroll()
。
navigation.addEventListener("manual", event => {
scroll: "manual",
event.intercept({
async handler() {
doSyncStuff();
// Handle scrolling earlier than by default:
event.scroll();
await doAsyncStuff();
}
});
});
restoreScroll()
方法目前仍可使用,但已淘汰,並將在 Chrome 108 版中移除。
結語
我們希望很快就能更新有關 Navigation API 的文章。在此同時,此 API 的規格包含許多網頁開發人員專用的資訊。