导航 API

实验性: 这是一项实验性技术
在将其用于生产之前,请仔细检查浏览器兼容性表格

导航 API(Navigation API)提供了启动、拦截和管理浏览器导航操作的功能。它还可以检查应用程序的历史记录条目。这是对之前 Web 平台特性(例如历史记录 APIwindow.location 的继承并解决了它们的缺点,且专门针对单页应用程序(SPA)的需求。

概念和用法

在 SPA 中,页面模板在使用过程中往往保持不变,而内容会在用户访问不同页面或功能时动态重写。因此,浏览器中只会加载一个不同的页面,这破坏了在浏览历史记录的不同位置之间来回导航的预期用户体验。此问题可以通过历史记录 API 在一定程度上得到解决,但它并非为满足 SPA 的需求而设计。导航 API 旨在弥补这一差距。

API 可通过 Window.navigation 属性访问,该属性返回对全局 Navigation 对象的引用。每个 window 对象都有自己对应的 navigation 实例。

处理导航

navigation 接口有几个相关事件,其中最值得注意的是 navigate 事件。当启动任何类型的导航时,都会触发此事件,这意味着你可以从一个核心位置控制所有页面导航,非常适合 SPA 框架中的路由功能。(但历史记录 API 并非如此,有时很难弄清楚如何响应所有导航。)navigate 事件处理器会传递一个 NavigateEvent 对象,其中包含详细信息,包括导航目的地的详细信息、类型、是否包含 POST 表单数据或下载请求等。

NavigationEvent 对象还提供两种方法:

  • intercept() 将返回 promise 的回调处理器函数作为参数。它允许你控制启动导航时发生的情况。例如,在 SPA 的情况下,它可用于根据导航到的 URL 的路径将相关的新内容加载到 UI 中。
  • scroll() 允许你手动启动浏览器的滚动行为(例如,到 URL 中的片段标识符),如果它对你的代码有意义,而不是等待浏览器自动处理它。

一旦启动导航并调用你的 intercept() 处理器,就会创建一个 NavigationTransition 对象实例(可通过 Navigation.transition 访问),可用于跟踪正在进行的导航的过程。

备注: 在此上下文中,“过渡”是指一个历史条目与另一个历史条目之间的过渡。它与 CSS 过渡无关。

备注: 对于大多数导航类型,你还可以调用 preventDefault() 来完全停止导航;尚未实现取消遍历导航的功能。

intercept() 处理器的 promise 兑现时,Navigation 对象的 navigatesuccess 事件将触发,允许你在成功导航完成后运行清理代码。如果它拒绝,意味着导航失败,则 navigateerror 将改为触发,允许你优雅地处理失败情况。NavigationTransition 对象上还有一个 finished 属性,它在触发上述事件的同时实现或拒绝,为处理成功和失败情况提供了另一种途径。

备注: 在导航 API 可用之前,要执行类似操作,你必须监听链接上的所有点击事件,运行 e.preventDefault(),执行适当的 History.pushState() 调用,然后根据新 URL 设置页面视图。而且这无法处理所有导航——只能处理用户发起的链接点击。

以编程方式更新和遍历导航历史记录

当用户浏览你的应用程序时,导航到的每个新位置都会导致创建导航历史记录条目。每个历史记录条目都由一个不同的 NavigationHistoryEntry 对象实例表示。这些实例包含多个属性,例如条目的键、URL 和状态信息。你可以使用 Navigation.currentEntry 获取用户当前所在的条目,并使用 Navigation.entries() 获取所有现有历史记录条目的数组。每个 NavigationHistoryEntry 对象都有一个 dispose 事件,当条目不再是浏览器历史记录的一部分时触发。例如,如果用户向后导航三次,然后向前导航到其他地方,则这三个历史记录条目将被丢弃。

备注: 导航 API 仅公开在当前浏览上下文中创建的与当前页面同源的历史记录条目(例如,不是嵌入式