Chrome 105 針對 Navigation API 的 NavigateEvent
推出了兩種新方法 (於 102 推出),改善在實際操作中造成問題的方法。intercept()
,可讓開發人員在導覽後控制狀態,並取代 transitionWhile()
,但這很難使用。scroll()
方法會捲動至網址中指定的錨點,並取代了不適用於所有類型導覽的 restoreScroll()
。
本文將說明兩者的問題,以及新方法如何解決這些問題。
NavigateEvent.transitionWhile()
在 Chrome 102 中導入 Navigation API 的 NavigateEvent.trasitionWhile()
方法,會攔截單一頁面應用程式中的用戶端轉場導覽。第一個引數能保證指示瀏覽器和網頁應用程式的其他部分已完成。
這個方法實際上的效果不佳。請思考以下常見的程式設計模式:
event.transitionWhile((async () => {
doSyncStuff();
await doAsyncStuff();
})());
這和下方程式碼的功能相同。這會在 API 偵測到開發人員打算攔截瀏覽之前,執行部分導覽部分。
doSyncStuff();
event.transitionWhile((async () => {
await doAsyncStuff();
})());
例如,這可能會在捲動還原邏輯中擷取到 DOM 改變 (而非之前) 的捲動位置。
異動情形
為了取代 transitionWhile()
,目前規格會導入 NavigateEvent.intercept()
。除了 transitionWhile()
支援的 focusReset
和 scrollRestoration
屬性以外,新方法還會接受處理常式。新的處理常式一律會在導覽提交後執行,並擷取捲動位置等項目,藉此避免發生 transitionWhile()
的問題。
transitionWhile()
方法仍可使用,但該方法已淘汰,並將在 Chrome 108 版中移除。
使用 截距()
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 的規格也包含許多專為網頁開發人員提供的資訊。