Chrome 105 在 Navigation API 的 NavigateEvent
中推出了兩種新方法 (在 102 版推出),以改善在實際操作中已證實有問題的方法。intercept()
,可讓開發人員在導覽後控制狀態,並取代 transitionWhile()
,但這變得難以使用。scroll()
方法會捲動至網址中指定的錨點,取代無法用於所有導覽類型的 restoreScroll()
。
本文將說明這兩種方法的問題,以及新方法如何解決這些問題。
NavigateEvent.transitionWhile()
NavigateEvent.trasitionWhile()
方法是在 Chrome 102 中與 Navigation API 一併推出,可攔截單頁應用程式中用於用戶端轉場的導覽。其第一個引數是承諾,可向瀏覽器和網頁應用程式的其他部分發出完成信號。
但實際上效果不佳。請考慮使用這個常見的程式設計模式:
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 的規格也包含許多專為網頁開發人員提供的資訊。