路由与 URL:让刷新、分享和返回都有道理

搜索到第三页,把链接发给朋友,对方却看到首页空白搜索框。页面内的状态可能没丢,但它从来没有写进地址。前端路由不仅是“点菜单换组件”,也是用户恢复上下文的方式。

哪些状态值得进入 URL

文章 ID、目录路径、搜索词、排序和页码通常适合 URL。输入焦点、菜单开关和临时草稿通常留在界面或专门的持久化机制中。密码、令牌和敏感个人信息不该放进查询字符串,因为地址可能进入历史记录、日志和 Referer。

Text
/knowledge/articles?q=vue&page=3&sort=updated

路由层解析并校验 page,不能把任意字符串直接当合法数字。关键词改变时往往应把页码归一,不然新查询仍停在第三页,用户会误以为没有结果。

push 与 replace 表达不同的历史意图

明确打开另一篇文章通常 push 新记录。搜索框每个按键都 push,会让返回键退几十次;可以在提交搜索时 push,在细小同步时 replace,或先保存本地输入、提交后才更新 URL。选择取决于产品交互,不是某个方法绝对更好。

直接打开深层地址也必须工作。纯 SPA 的托管需要将页面路由回退到入口 HTML,同时保留静态资源与 API 的正确路由;SSR 框架则由服务端路由处理。若只有从首页点击才能打开,复制链接就 404,部署配置还没完成。

路由变化不一定卸载组件

从 /articles/a 到 /articles/b 可能复用同一组件。只在 mounted 中加载一次文章就会留下 A 的内容。观察需要的参数,或使用路由框架的数据机制重新获取,并处理旧请求失效。

Vue Router 的导航守卫适合登录跳转、离开未保存编辑器的提示等;React Router 有 Declarative、Data、Framework 等模式,loader/action 等能力需要对应模式。阅读教程时先看它使用哪种路由模式,别混装不同年代的 API。

权限校验放到可信边界

前端守卫能改善体验,但用户可以直接请求接口。文章是否可读、能否发布,仍由服务端或数据库 RLS 校验。404、403 和加载失败也要有区分,别一律跳登录,否则坏链接会被误判为账号问题。

跳转回来时只接受站内允许的 returnTo 路径,防止把登录完成的用户引到攻击者网站。未保存提示不能保证数据永不丢失,重要草稿还需要明确的保存机制。

练习与参考

完成搜索后刷新,复制地址到新标签页,再用返回键恢复上一查询。三条路径应看到符合预期的内容;手动填入 page=-1 或非数字时也应回到合法状态。

从地址栏到页面状态,做一次手工验收

先规定 URL 契约:q 是关键词,page 是从 1 开始的正整数,sort 只允许 updated 或 title。读取时对缺失、非法和超范围值做处理,再把合法结果交给页面。parseInt('2abc') 会得到 2,所以如果契约要求完整数字,不能只靠 parseInt 判断有效性。

可以先检查字符串是否匹配正整数形式,再 Number 转换并确认 Number.isSafeInteger;同时限制允许的最大页码或交由后端分页协议校验。类型写成 number 并不代表任意地址栏字符串已经被验证。

接着测试四条路径:从首页点击进入、直接粘贴深层地址、刷新、返回上一页。它们分别覆盖客户端导航、服务器入口、初始化和历史恢复。只测试第一条,会漏掉常见的 SPA 回退配置问题。

登录回跳也要校验实际目标。只检查 startsWith(‘/’) 不够,因为 //example.com 在 URL 解析中可能表示另一个主机。使用受控的站内路径集合,或基于当前站点解析并严格比较 origin,再决定是否允许导航。