你以为 SPA 路由只能靠框架自己写?今天浏览器把这件事彻底原生化了
做过 SPA 的人都知道,只要项目里要写路由,就离不开这套流程:给每个链接加 click 监听,调用 pushState 之后手动更新 URL,处理 popstate 事件,还要记得处理浏览器后退前进——这一套下来,路由代码比业务逻辑还多。
问题在于,History API 从来就不是为 SPA 设计的。它是给多页面网站打的一个补丁,我们用了十几年,把这个补丁当成了标准。
Navigation API 就是来取代它的。作为 History API 的继任者,它在 2026 年 1 月正式达到 Baseline Newly Available 状态,Chrome、Edge、Firefox 147 和 Safari 26.2 全部支持,覆盖全球约 93% 的用户。
一个事件,处理所有导航
Navigation API 的核心是一个全局的 navigate 事件。它会在任何导航行为触发时 fires:用户点击链接、表单提交、浏览器后退前进、甚至直接调用 navigation.navigate()——全部包括,不需要像以前那样给每个场景写独立的处理逻辑。
navigation.addEventListener("navigate", (navigateEvent) => {
// 跨域、下载、hash 变化等情况不需要拦截
if (!navigateEvent.canIntercept || navigateEvent.hashChange) return;
const url = new URL(navigateEvent.destination.url);
if (url.pathname.startsWith("/articles/")) {
navigateEvent.intercept({
async handler() {
renderPlaceholder();
const content = await fetchArticle(url.pathname);
renderArticle(content);
},
});
}
});
intercept() 是关键。这个方法让浏览器知道「我接管了这个导航,它是同文档更新,可能需要一点时间」。有了这个语义,浏览器会显示原生 loading 指示器,用户点击停止按钮可以取消导航,而且整个过程对无障碍访问完全透明——这些以前全都要自己写。
异步路由自己会取消
以前写异步路由最麻烦的是:用户点了链接 A,加载到一半又点了链接 B,等 A 的数据回来页面已经乱了。Navigation API 用 AbortSignal 解决了这个问题。
navigateEvent.intercept({
async handler() {
const res = await fetch(url, { signal: navigateEvent.signal });
render(await res.json());
},
});
navigateEvent.signal 在用户触发新导航时自动 abort,A 请求变成废数据,render 根本不会跑。race condition 和页面闪烁从此消失。
状态管理也原生了
Navigation API 还把历史状态的管理也接管了。以前你要么用额外的 state 库,要么把状态塞进 sessionStorage,读取时再解析。现在一行代码搞定:
// 写入状态
navigation.updateCurrentEntry({ state: { sidebarOpen: true } });
// 读取当前状态
const current = navigation.currentEntry.getState();
navigation.entries() 可以拿到同源所有历史记录,navigation.traverseTo(key) 直接跳转到任意一条历史——这些操作 History API 根本做不到。
框架路由会消失吗?
React Router、TanStack Router 这些框架路由目前在讨论接入 Navigation API 作为底层,但 Navigation API 不是来取代框架路由的。它的定位是浏览器原生基础设施,为框架提供更底层的能力。以后框架可能会基于 Navigation API 构建,自己手写路由的项目则可以直接用平台能力省掉一个依赖。
迁移很简单:把原来的 pushState 替换成 navigation.navigate(),把 popstate 监听换成 navigate 事件监听,scrollRestoration 浏览器自动处理,focus 管理浏览器自动做。如果要兼容旧浏览器,加一个 feature detection 就行:
if ("navigation" in window) {
// Navigation API
} else {
// History API
}
Navigation API 覆盖了约 93% 的全球用户,主流框架正在逐步接入。下次新建一个不需要框架的小项目,可以试试直接用 Navigation API,看看那个「写路由」的工作是不是真的消失了。
评论区
登录后可评论。