SPA架构核心是路由驱动视图、状态驱动行为:路由决定“用户在哪”,状态决定“页面显示什么、能做什么”;需声明式路由配置、按作用域分层管理状态、同步可分享状态到URL、服务端预留通配路由接口。

单页应用(SPA)的架构核心在于路由驱动视图、状态驱动行为,而不是靠后端跳转或整页刷新。关键不在于用哪个框架,而在于如何让路由和状态协同工作——路由决定“用户在哪”,状态决定“页面显示什么、能做什么”。
路由层:声明式定义 + 动态响应
现代 SPA 通常采用声明式路由配置(如 React Router 的 、Vue Router 的 createRouter({ routes })),而非手动监听 URL 变化。重点是:
- 路径与组件一对一映射,支持嵌套路由(如
/user/123/profile对应UserLayout → ProfileView) - 路由参数(
:id)、查询参数(?tab=logs)、哈希(#settings)统一由路由库解析并注入组件,不手动 parselocation.search - 导航用编程式 API(
navigate('/post/42')或router.push()),避免直接改window.location,确保路由状态可回溯、可拦截(如守卫逻辑)
状态管理:按作用域分层,不一刀切
不是所有状态都该进全局 store。合理分层更轻量、更易维护:
-
路由相关状态:URL 参数、搜索条件、分页页码等,直接从路由对象读取(如
useParams()、useSearchParams()),无需存入 Redux/Vuex —— 它们本就是路由的一部分 -
组件局部状态:表单输入、折叠展开、临时筛选项,用
useState或ref即可,不升级为全局状态 - 跨视图共享状态:用户登录信息、主题偏好、实时通知数等,适合放入全局状态管理器,但需配合持久化(如 localStorage 同步)和初始化逻辑(避免白屏时状态为空)
路由与状态的联动:避免“状态漂移”
常见问题:用户修改筛选条件(状态变),但 URL 没更新;或手动改 URL 后,页面没重新加载对应数据。解决方式:
立即学习“Java免费学习笔记(深入)”;
- 把可分享、可书签的状态(如搜索关键词、tab 选中项)同步到 URL 查询参数,并在路由变化时自动触发数据重载(例如监听
useSearchParams变化调用fetchData()) - 对依赖路由参数的数据请求,放在路由组件内执行(非全局 effect),保证每次进入该路由都拿到最新参数对应的数据
- 需要保留滚动位置或表单草稿?用路由的
key属性(如)或自定义 hook 管理路由级状态快照
服务端协作:SSR/SSG 不是必须,但要预留接口
纯前端 SPA 也能做 SEO 和首屏优化,关键是让服务端能识别路由意图:
- 服务端配置通配路由(如 Nginx 的
try_files $uri $uri/ /index.html),把所有前端路由交由 JS 处理 - 若需 SSR,路由配置必须可服务端执行(如不依赖
window),且数据预取逻辑与路由声明紧耦合(如 Next.js 的getServerSideProps基于页面文件路径) - 动态路由(如
/post/[id])需服务端生成静态路径列表(getStaticPaths)或支持 fallback,否则直出 404
不复杂但容易忽略:路由是 SPA 的骨架,状态是血肉,两者对齐了,应用才不会“走样”。











