Chrome 中的 NavigationEvent 变化 105

Joe Medley
Joe Medley

Chrome 105 在 Navigation API 的 NavigateEvent 中引入了两个新方法(在 102 版中引入),以改进在实践中证明存在问题的方法。intercept() 可让开发者在导航后控制状态,取代了事实证明难以使用的 transitionWhile()scroll() 方法可滚动到网址中指定的锚点,取代了并非对所有导航类型都有效的 restoreScroll()

在本文中,我将说明这两种方法存在的问题,以及新的方法如何解决这些问题。

Chrome 102 中随 Navigation API 引入的 NavigateEvent.trasitionWhile() 方法可拦截单页应用中的客户端转换的导航。它的第一个参数是一个 promise,向浏览器和 Web 应用的其他部分表明已完成。

这种方法在实际操作中表现不佳。我们来考虑以下常见的编码模式:

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

其功能等同于以下代码。这会导致在 API 知晓开发者想要拦截导航之前,导航的某些部分运行。

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

例如,滚动恢复逻辑可能会使应用出现混乱,其中会捕获 DOM 更改之后(而不是之前)的滚动位置。

具体变化

为了替换 transitionWhile(),当前规范引入了 NavigateEvent.intercept()。除了 transitionWhile() 支持的 focusResetscrollRestoration 属性之外,新方法还采用处理程序。新的处理程序始终在提交导航并且捕获滚动位置等内容后运行,从而避免 transitionWhile() 的问题。

transitionWhile() 方法仍然可用,但已弃用,并将在 Chrome 108 中移除。

使用 continue()

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 的规范包含专门针对 Web 开发者的大量信息。

照片由 Tim Gouw 提供,由 Unsplash 提供