第 6 章 · 框架选型与 academy-demo 重构
本章目标:建立 Vue / React / 原生 选型方法论;明确何时用框架、何时保留原生或引入 SSR;提供将 frontend-web ch16 毕业项目 分别重构为 academy-demo-vue / academy-demo-react 的检查清单、目录对照、迁移步骤与 100 分答辩验收表;展望 TypeScript、Next.js、Nuxt。
学时建议:3 小时(阅读 + 规划)+ 8~12 小时(重构实战,课外)
前置:完成本模块 ch01~ch05 与 frontend-web ch16 毕业项目。
6.1 三种路线总览
frontend-web ch16(原生 Vite)
│
┌────┴────┐
▼ ▼
academy- academy-
demo-vue demo-react
(ch01-03) (ch04-05)
| 仓库 | 技术栈 | 对应章节 |
|---|
| academy-demo | 原生 JS + 多 HTML | frontend-web ch16 |
| academy-demo-vue | Vue 3 + Router + Pinia | 本模块 ch01~03 |
| academy-demo-react | React 18 + Router + Hooks | 本模块 ch04~05 |
重构不是重写业务,而是同一产品规格换实现层,验收标准与 ch16 对齐并叠加框架最佳实践。
6.2 Vue vs React vs 原生对比
| 维度 | 原生 JS(ch16) | Vue 3 | React 18 |
|---|
| 学习曲线 | 最低,直接 DOM | 中等,模板+响应式直观 | 中等,JSX+Hooks 概念多 |
| 模板 | 字符串/HTML 文件 | 单文件 .vue 模板 | JSX in JS |
| 状态 | 手写 state | ref/reactive/Pinia | useState/Context/Zustand |
| 生态 | 自选拼凑 | Vue Router/Pinia/Element Plus | React Router/Redux/Ant Design |
| 招聘市场 | 偏维护老项目 | 国内中小厂、政务、后台多 | 大厂、跨端、海外多 |
| 包体积 | 最小(无框架) | 运行时 ~34KB gzip | 运行时 ~45KB gzip |
| TS 支持 | JSDoc | 良好(Volar) | 极佳(生态默认 TS) |
| 适用场景 | 落地页、嵌入页、极简 H5 | 中后台、运营配置、快速 CRUD | 复杂交互、设计系统、跨端 |
| SSR 方案 | 不适用 | Nuxt 3 | Next.js |
行业案例 · 贤紫优选商城:C 端商城 H5 活动页保持 原生 + Vite(首屏 < 80KB);商户后台用 Vue 3(表单密集);数据运营大屏用 React(表格+图表组件生态)。同一后端 OpenAPI,三端并行,按场景选型而非统一技术宗教。
6.3 何时用框架、何时原生、何时 SSR
6.3.1 决策树
页面是否需要复杂组件状态与多页共享?
├─ 否 → 原生 / 静态站(ch16 足够)
└─ 是 → 需要 SEO 首屏在服务端渲染?
├─ 否 → SPA:Vue 或 React(本模块)
└─ 是 → Nuxt / Next(SSR/SSG)
| 场景 | 推荐 | 理由 |
|---|
| 营销落地页、单页活动 | 原生或 Astro | 极致首屏、少 JS |
| 学院课程门户(ch16) | 原生或 SPA | 无强 SEO,Mock 演示 |
| 商城商品详情 SEO | Nuxt/Next SSR | 爬虫可读、分享卡片 |
| 商户后台 CRUD | Vue 3 + UI 库 | 表单表格成熟 |
| 实时协作白板 | React + 状态库 | 细粒度更新、生态 |
6.3.2 不选框架的信号
- 总 JS < 50KB,交互少于 3 个状态字段
- 生命周期 < 3 个月的一次性页
- 强依赖现有 jQuery 插件且无迁移预算
- 团队零前端编制,仅运维维护
6.3.3 必须上 SSR 的信号
- 核心流量来自搜索引擎且内容动态
- 首屏 LCP 在 3G 网络必须 < 2.5s 且客户端包已优化仍不达标
- 社交分享依赖服务端注入 og 标签(也可用 prerender 折中)
6.4 ch16 → Vue 重构检查清单
6.4.1 功能映射
| ch16 Must | Vue 实现 | 完成 □ |
|---|
| 首页 Hero + 精选 | HomeView.vue | |
| 课程列表搜索防抖 | useDebounce composable + store | |
| 标签筛选 | courses.activeTag + computed | |
| 课程详情 + 章节 | CourseDetailView + fetchChapters | |
| 待办 CRUD | TodoView + localStorage | |
| 响应式 320~1440 | tokens.css + Grid | |
| 收藏 | favorites store | |
npm run build | Vite 默认 | |
6.4.2 目录对照
| ch16 原生 | academy-demo-vue |
|---|
index.html + main.js | views/HomeView.vue |
courses.html | views/CourseListView.vue |
course.html?id= | router /courses/:id |
todo.html | views/TodoView.vue |
components/course-card.js | components/CourseCard.vue |
api/client.js | api/client.js(保留) |
utils/debounce.js | composables/useDebounce.js |
utils/storage.js | Pinia + localStorage | |
style/tokens.css | assets/tokens.css |
6.4.3 迁移步骤(建议 4 天)
| 天 | 任务 | 产出 |
|---|
| D1 | 初始化项目、路由四页空壳、Header | 可点击导航 |
| D2 | Pinia courses + 列表页 parity | 搜索筛选与 ch16 一致 |
| D3 | 详情章节、Todo、favorites | 主链路打通 |
| D4 | 响应式、a11y、build、README | 可部署 dist |
6.5 ch16 → React 重构检查清单
6.5.1 功能映射
| ch16 Must | React 实现 | 完成 □ |
|---|
| 四页面 | Routes + pages/* | |
| 搜索防抖 | useDebounce | |
| 课程卡片 | CourseCard.jsx | |
| 详情 | CourseDetailPage + useParams | |
| 待办 | useTodos + TodoPage | |
| 主题切换 | useLocalStorage('theme') | |
| 错误/加载态 | 各页三态 UI | |
6.5.2 目录对照
| ch16 原生 | academy-demo-react |
|---|
| 多 HTML 入口 | 单页 main.jsx + Router |
components/header.js | layouts/AppLayout.jsx |
state 散落各 js | hooks/useCourses.js 等 |
| 全局样式 | index.css + CSS Modules |
6.5.3 迁移注意点
| 坑 | 说明 |
|---|
| 状态提升 | 收藏、课程列表放 Context 或单页父级 |
| 路由 state | navigate('/todo', { state }) 替代 query 传对象 |
| 严格模式 | StrictMode 下 effect 双调用,注意清理函数 |
| SEO | SPA 需 prerender 插件或接 SSR 才等同 ch16 meta |
6.6 质量门禁(继承 ch16)
重构项目除功能 parity 外,须保留 ch16 质量底线:
| 类别 | 标准 |
|---|
| Lighthouse 移动 Performance | ≥ 85 |
| a11y | 无 axe critical;键盘可操作 |
| 安全 | 无 dangerouslySetInnerHTML 裸用用户输入 |
| 文档 | README:安装、脚本、环境变量、部署 |
| Mock | public/mock 与 ch16 数据兼容 |