Chrome 105 版中的 NavigationEvent 異動

Joe Medley
Joe Medley

Chrome 105 針對 Navigation API 的 NavigateEvent 推出了兩種新方法 (於 102 推出),改善在實際操作中造成問題的方法。intercept(),可讓開發人員在導覽後控制狀態,並取代 transitionWhile(),但這很難使用。scroll() 方法會捲動至網址中指定的錨點,並取代了不適用於所有類型導覽的 restoreScroll()

本文將說明兩者的問題,以及新方法如何解決這些問題。

在 Chrome 102 中導入 Navigation API 的 NavigateEvent.trasitionWhile() 方法,會攔截單一頁面應用程式中的用戶端轉場導覽。第一個引數能保證指示瀏覽器和網頁應用程式的其他部分已完成。

這個方法實際上的效果不佳。請思考以下常見的程式設計模式:

event.transitionWhile((async () => {
  doSyncStuff();
  await doAsyncStuff();
})());

這和下方程式碼的功能相同。這會在 API 偵測到開發人員打算攔截瀏覽之前,執行部分導覽部分。

doSyncStuff();
event.transitionWhile((async () => {
  await doAsyncStuff();
})());

例如,這可能會在捲動還原邏輯中擷取到 DOM 改變 (而非之前) 的捲動位置。

異動情形

為了取代 transitionWhile(),目前規格會導入 NavigateEvent.intercept()。除了 transitionWhile() 支援的 focusResetscrollRestoration 屬性以外,新方法還會接受處理常式。新的處理常式一律會在導覽提交後執行,並擷取捲動位置等項目,藉此避免發生 transitionWhile() 的問題。

transitionWhile() 方法仍可使用,但該方法已淘汰,並將在 Chrome 108 版中移除。

使用 截距()

NavigateEvent.intercept() 的限制與 transitionWhile() 相同,因為無法在所有導覽事件上呼叫。無法攔截跨來源瀏覽,也無法跨文件週遊。這樣做會擲回 "SecurityError" 類型的 DOMException

如要使用 intercept(),只要在呼叫自訂處理常式時傳遞自訂處理常式即可。

navigation.addEventListener("navigate", event => {
  event.intercept({
    async handler() {
      doSyncStuff();
      await doAsyncStuff();
    }
  });
});

從頁面頂端到錨定標記 (從 /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 的規格也包含許多專為網頁開發人員提供的資訊。

相片來源:Tim Gouw,發表於 Unsplash 網站上