前端路由核心是拦截URL变化、不刷新页面、按路径匹配渲染视图;需用history.pushState和popstate事件实现,避免hashchange,注意SEO、滚动复位、标题更新等细节。
JavaScript 实现前端路由,核心不是“写个跳转函数”,而是**拦截 URL 变化、不刷新页面、按路径匹配渲染对应视图**。现代 SPA 路由本质是 history.pushState + window.addEventListener('popstate') 的组合,手动实现几行就能跑通,但真实项目中必须处理好路由嵌套、参数解析、滚动复位、动态加载等细节。
适合学习原理或超轻量场景(比如嵌入式面板、微前端子应用)。关键点在于:不触发页面刷新,靠浏览器历史 API 操作地址栏,再监听变化来切换内容。
history.pushState() 替代 window.location.href = '/xxx',避免刷新popstate 事件捕获后退/前进,而不是只监听 hashchange(后者兼容性好但 URL 带 #)URLPattern(Chrome 110+),避免简单 === 字符串比对(如 /user/123 和 /user/456 都该命中 /user/:id)function route(path, handler) {
if (location.pathname === path) handler();
}
window.addEventListener('popstate', () => route('/about', renderAbout));
history.pushState({}, '', '/about');手写基础逻辑没问题,但一旦涉及嵌套路由、懒加载、

React Router v6 的 createBrowserRouter 内置了 loader、errorElement、useNavigate 等完整生命周期,且与并发渲染兼容Vue Router 4 的 createRouter({ history: createWebHistory() }) 默认启用 HTML5 History 模式,无需 Nginx 配置 fallback 就能支持深层路由(前提是服务端已配好)scrollRestoration: 'manual' 导致后退时页面卡在底部,或忘记调用 history.scrollRestoration = 'auto' 恢复默认行为不是“哪个更高级”,而是部署约束和 SEO 行为不同。选错会导致线上 404 或搜索引擎抓不到内容。
pushState 路由(/user/123):需服务端配置 fallback(如 Nginx 返回 index.html),否则直接访问深层链接会 404;但 URL 干净,利于 SEOhash 路由(/#user/123):完全由前端控制,无需服务端配合;但搜索引擎可能忽略 # 后内容,且 location.hash 不触发 popstate,得监听 hashchange
pushState 后,location.pathname 立即更新;而修改 location.hash 不会触发页面刷新,但会触发 hashchange 事件这些点不报错,但上线后用户感知极差,且很难被测试覆盖。
document.title 不随路由自动更新——必须在路由切换回调里显式设置,否则所有页面标题都是初始值document.body.focus({ preventScroll: true }) 或聚焦到主内容区React.lazy + Suspense 必须配 Fallback,否则白屏;Vue 的 defineAsyncComponent 也要设 errorComponent
真正难的从来不是“怎么跳转”,而是让每次跳转都像原生页面一样自然:URL 正确、标题正确、焦点正确、滚动位置合理、错误可感知。这些细节堆起来,才是用户说“这网站真快”的原因。