如何选对 app-router 导航模式:hashchange、pushState 与 router.go() 三大方案全指南
【免费下载链接】app-routerRouter for Web Components项目地址: https://gitcode.com/gh_mirrors/ap/app-router
app-router是一个面向 Web Components 的前端路由组件,支持 Polymer、X-Tag 以及原生自定义元素。它通过监听hashchange和popstate事件管理页面状态、懒加载内容,并自动绑定路径变量与查询参数。本文将带你快速掌握 hashchange、HTML5 pushState 和router.go()三种导航方案的区别与选型方法。
三种导航方案一览
| 方案 | URL 形态 | 触发事件 | 需要额外组件 | 适用场景 |
|---|---|---|---|---|
| hashchange | #/home | hashchange | 否 | 纯静态托管、兼容老浏览器 |
| pushState | /home | popstate | pushstate-anchor | 现代浏览器、干净的 URL |
| router.go() | 取决于 mode | popstate | 否(需设置 mode) | 代码中编程式跳转、重定向 |
方案一:hashchange——零配置的路由导航
hash 模式是最简单、兼容性最好的选择。只需在页面里放一个普通的<a>标签:
<a href="#/home">Home</a>点击后浏览器触发hashchange事件,路由器找到第一个匹配的<app-route>并加载对应内容,完全不需要你自己写事件监听代码。注意 hash 路径#/home会自动匹配不带#的path="/home"路由(见 src/app-router.js 中parseUrl()对#/和#!/前缀的解析逻辑)。
hash 模式的优点:
- 无需服务端配置,扔到任何静态服务器都能跑
- URL 中带
#,刷新不会 404 - 支持二级 hash 滚动定位,如
#/page1#middle会自动滚动到id="middle"的元素(测试页面:test-scroll-hash-mode.html)
缺点则是 URL 不够美观,且 hash 部分不会发送到服务器。
方案二:pushState——HTML5 历史 API 的现代导航
想要/home这样干净的路径,可以借助pushstate-anchor或html5-history-anchor扩展<a>标签:
<a is="pushstate-anchor" href="/home">Home</a>点击时它会调用pushState()并派发popstate事件,路由器同样自动响应。测试示例可参考 test-scroll-pushstate-mode.html,其中路由器通过mode="pushstate"强制锁定该模式。
pushState 的优点:
- URL 干净、可分享、利于 SEO
- 可完整使用浏览器前进/后退按钮
注意事项:
- 需要服务端配合,保证
/home等路径返回正确内容 - 部分旧版 IE/Edge 中
hashchange不会触发popstate,源码里已做兼容处理(src/app-router.js 第 114-118 行的 IE/Edge 补丁)
方案三:router.go()——JavaScript 编程式跳转
当你需要在代码中主动导航(比如表单提交成功后跳走、页面加载后自动重定向),可以直接调用路由器的go(path, options)方法:
document.querySelector('app-router').go('/home'); // 或替换当前历史记录,而不是新增一条 document.querySelector('app-router').go('/home', {replace: true});go()的实际行为取决于路由器的mode属性(实现见 src/app-router.js 中AppRouter.go函数):
mode="hash"或默认auto:拼接成#/home再写入历史mode="pushstate":直接写入/homemode="hashbang":写入#!/home,用于 Google 爬虫抓取 SPA
关键点:使用go()或redirect时,务必显式设置mode,否则会默认改 hash,而不是你以为的 pushState:
<app-router mode="pushstate"> <!-- app-routes --> </app-router>实战例子:在 test-bindrouter.html 中,页面通过bindRouter属性拿到路由器引用,在attachedCallback生命周期里调用this.router.go('/other')实现自动跳转——这是"进入页面即重定向"的典型用法。
三大方案怎么选?
选 hashchange,如果:
- 项目部署在纯静态服务器(GitHub Pages、S3 等),无法配置服务端路由回退
- 需要兼容不支持 History API 的老浏览器
- 项目处于原型阶段,想快速跑通
选 pushState,如果:
- 面向现代浏览器,URL 美观和专业度是刚需
- 后端可配置"未知路径返回 index.html"的回退规则
- 希望爬虫和搜索引擎索引完整页面路径
用 router.go(),当:
- 导航由程序逻辑触发(权限校验、表单成功、登录态变更)
- 路由带
redirect属性——它内部就是调用go(redirect, {replace: true}),保证"重定向"不产生多余历史记录 - 嵌套路由器场景,配合
<app-route onUrlChange="updateModel">只更新模型不刷新整页(示例:test-onurlchange.html)
常见问题
问:能混用两种模式吗?
可以。同一组路由同时兼容普通路径/和 hash 路径#/,路由器会根据实际 URL 判断。但建议用mode="auto|hash|pushstate"显式锁定,避免auto模式下重定向和go()意外走 hash。
问:/home和/home/会被当成两个路由吗?
默认(trailingSlash="strict")会。加上trailingSlash="ignore"属性即可让两者匹配同一路由。
问:URL 中只改了 hash 片段会重新加载页面吗?
不会。源码中的stateChange()会对比previousUrl,发现仅 hash 变化时只执行滚动定位(scrollToHash),不触发路由切换,性能友好。
写在最后
三种方案本质殊途同归:hashchange 和 pushState 负责"用户点链接"的场景,router.go()负责"代码做决策"的场景,而mode属性决定了它们的落地方式。理解 changelog.md 中 v2.6.1 引入 hashbang 模式、v1.0.0 用mode取代旧pathType的演进过程,也能帮你避开老教程中的过时写法。按需组合三者,即可覆盖 Web Components 应用的全部导航需求。
【免费下载链接】app-routerRouter for Web Components项目地址: https://gitcode.com/gh_mirrors/ap/app-router
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考