构建现代SPA需选对核心机制:用createBrowserRouter并配置服务端fallback,状态更新须避免直接mutation,useEffect依赖数组要完整,否则引发无限请求或状态滞留。

JavaScript 构建现代单页面应用(SPA)不靠“教程式堆砌”,而靠选对核心机制、避开常见断裂点。关键判断:你不需要从零手写路由和状态同步,但必须理解框架底层如何响应 URL 变化、何时触发组件重渲染、以及数据流在何处脱钩。
用 createBrowserRouter 替代 HashRouter 处理真实路径
很多初学者卡在刷新 404——根本原因是用了 HashRouter(URL 带 #),却部署到不支持 History API 回退的静态服务器。现代 SPA 应默认走 createBrowserRouter,它依赖浏览器原生 history.pushState,但要求服务端将所有路径 fallback 到 index.html。
- 开发时 Vite/webpack-dev-server 默认支持,无需配置
- Nginx 需添加
try_files $uri $uri/ /index.html; - Cloudflare Pages 或 GitHub Pages 需启用 “Single Page Applications” 选项,否则 404 不会重定向
- 不要在
createBrowserRouter的routes中漏写errorElement,否则路由匹配失败时白屏无提示
状态更新必须绕过直接 mutation,哪怕只是数组 push
React/Vue/Svelte 的响应式系统不监听对象属性赋值或数组原地方法(如 push、splice)。看似“更新了数据”,实际 UI 不变,且后续依赖该状态的逻辑可能读到旧值。
- React 中改用
setItems(prev => [...prev, newItem]),而非items.push(newItem) - Vue 3 的
ref数组也一样:items.value = [...items.value, newItem] - Svelte 中使用
$: derivedItems = items.map(...)比手动更新更安全 - 若用 Zustand 或 Jotai,仍需避免在
setState回调里修改传入的 draft 对象——它们不是 Immer
useEffect 依赖数组漏项会导致无限请求或状态滞留
这是 SPA 中最隐蔽的 bug 来源之一:你以为请求只发一次,结果每次渲染都触发;或者过滤条件变了,但请求参数还是上一轮的值。
采用zblog修改的模板,简单方便,直接解压上传到空间即可使用,页面简单,适合SEO,导航,次导航,最新文章列表,随机文章列表全部都有,网站采用扁平结构,非常适用淘宝客类小站,所有文章都在根目录下。所有需要修改的地方在网页上各个地方都有标注说明,一切在网站后台都可以修改,无须修改任何程序代码,是新手的不二选择。后台登陆地址: 域名/login.asp用户名:admin (建议不要修改)密码:adm
立即学习“Java免费学习笔记(深入)”;
- API 请求若依赖
searchTerm,依赖数组必须包含searchTerm,不能只写[fetchData] - 函数本身(如
fetchData)若在组件内定义且捕获了 props/state,它本身也应加入依赖,或用useCallback包裹 - 空依赖数组
[]并不等于“只运行一次”——如果函数内引用了未声明的 prop,它会闭包旧值,导致 stale closure - 用 ESLint 插件
eslint-plugin-react-hooks可强制检查,但无法替代手动验证逻辑流
真正难的不是写出能跑的 SPA,而是当路由嵌套三层、异步数据加载中又触发权限变更、同时有多个表单在编辑时,状态还能保持一致。这时候,硬编码的 useState 和裸写的 fetch 会迅速失焦——得靠明确的数据生命周期设计,而不是更多“技巧”。










