Week 1-8: Spring Boot 学习计划完整项目

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-29 23:45:17 +08:00
commit f95aa18724
201 changed files with 18595 additions and 0 deletions

226
week6/教案.md Normal file
View File

@@ -0,0 +1,226 @@
# Week 6Vue 3 前端框架入门
**目标**:掌握 Vue 3 Composition API + Vite + Vue Router + Pinia能独立开发 SPA 应用。
**前置**:已完成 Week 5 Spring Boot 后端,有 HTML/CSS/JS 基础。
**本周产出**:一个独立的 Todo SPA 应用,包含计数器、动态表单、组件拆分、路由导航、状态管理和 HTTP 封装。
**启动方式**
```bash
cd week6
npm install # 首次运行
npm run dev # 启动开发服务器 → http://localhost:5173
```
---
## Day 1Vue 3 介绍、Vite 脚手架、组件基础
**知识点**
- Vue 3 是什么:渐进式前端框架,核心是"响应式数据 + 声明式渲染"
- SFCSingle File Component`.vue` 文件 = `<template>` + `<script setup>` + `<style scoped>`
- Composition API vs Options API为什么选 Composition API
- Vite新一代构建工具冷启动快ES Module、HMR 极速
- 项目结构:`main.js`(入口)、`App.vue`(根组件)、`components/``views/`
**动手 → 理解**
1. 打开 `src/main.js`:理解 `createApp(App).mount('#app')` 的过程
2. 打开 `src/App.vue`:观察 `<script setup>` 语法糖
3. 修改 `index.html` 中的 `<title>`,观察浏览器标签变化
4.`HomeView.vue``<template>` 中加一行 `<p>Hello Vue!</p>`,观察热更新
5.`style scoped` 去掉,观察样式是否泄漏到其他组件
**核心文件**
- `index.html` — 入口 HTML`<div id="app">` 挂载点
- `src/main.js` — 应用初始化
- `src/App.vue` — 根组件
- `vite.config.js` — Vite 配置(插件、代理、端口)
**思考题**`<script setup>` 和普通的 `<script>` 有什么区别?为什么 Vue 3 推荐 setup 语法糖?
---
## Day 2响应式数据ref/reactive、计算属性
**知识点**
- `ref()`包装基本类型number、string、boolean通过 `.value` 访问
- `reactive()`:包装对象/数组,直接访问属性(不需要 `.value`
- `computed()`:计算属性,依赖变化时自动重新计算,带缓存
- `watch()` / `watchEffect()`:侦听数据变化执行副作用
- 响应式的本质Proxy 拦截 getter/setter数据变 → 视图自动变
- 模板中 ref 自动解包(不需要写 `.value`
**动手 → 理解**
1. 打开 `CounterView.vue`,在模板中写 `{{ localCount }}`,不需要 `.value`
2.`<script>` 中用 `console.log(localCount.value)` 打印当前值
3. 修改 `computed` 的计算逻辑,改为判断"是否大于 10"
4. 添加一个 `watch`,在 `localCount` 变化时 `console.log('变了:', newVal)`
5. 对比:把 `reactive` 改为 `ref` 写一个对象,体会 `.value` 的区别
**核心文件**
- `views/CounterView.vue` — ref + computed 演示
- `stores/counter.js` — Pinia store第 6 天预热)
**思考题**:为什么模板中 ref 自动解包,但 `<script>` 里必须用 `.value`
---
## Day 3指令系统v-if/v-for/v-model
**知识点**
- `v-if` / `v-else-if` / `v-else`:条件渲染(销毁/重建 DOM
- `v-show`:条件显示(仅切换 `display`)—— 适合频繁切换
- `v-for`:列表渲染,必须有 `:key` 唯一标识
- `v-bind`(缩写 `:`):动态绑定属性 `:class``:style``:href`
- `v-model`:双向绑定,表单输入 ↔ 数据自动同步
- `v-on`(缩写 `@`):事件绑定 `@click``@submit``@keyup`
- `v-model` 修饰符:`.trim``.number``.lazy`
**动手 → 理解**
1. 打开 `FormDemoView.vue`,在输入框中输入,观察下方实时预览
2. 用 DevTools 检查:勾选"显示详细信息"时,`v-if` 的元素是否在 DOM 中?
3.`v-if` 换成 `v-show`,再次检查 DOM 差异
4.`v-for``<li>` 中故意不写 `:key`,观察控制台警告
5. 尝试加一个 `v-model.lazy` 的输入框,对比 `input` 事件和 `change` 事件的区别
**核心文件**
- `views/FormDemoView.vue` — 指令综合演示
**思考题**:什么时候用 `v-if`,什么时候用 `v-show`?为什么 `v-for``v-if` 不建议同时使用?
---
## Day 4组件通信props/emits、插槽
**知识点**
- `defineProps()`:父组件向子组件传递数据(单向数据流)
- `defineEmits()`:子组件向父组件发送事件(回调模式)
- Prop 校验:`type``required``default``validator`
- 单向数据流原则:子组件不能直接修改 props
- `v-model` 组件版:`modelValue` + `update:modelValue`
- `<slot>` 插槽:父组件向子组件传递模板内容
- 命名插槽、作用域插槽(高级)
**动手 → 理解**
1. 打开 `TodoForm.vue``TodoItem.vue`,对照看 props 和 emits
2.`TodoItem` 中尝试直接 `todo.done = true`(不通过 emit观察 Pinia 是否感知
3.`TodoItem` 的 props 加一个 `validator`,限制 `todo.text` 不能为空
4. 练习:新建一个 `<Card>` 组件,用 `<slot>` 让父组件填充内容
5. 尝试用 `v-model` 模式改写 `TodoForm`(父组件用 v-model 双向绑定输入值)
**核心文件**
- `components/TodoForm.vue` — props 接收 / emits 发送
- `components/TodoItem.vue` — props 接收 / emits 发送
- `views/TodoView.vue` — 父组件,组装 TodoForm + TodoItem
**思考题**:为什么不直接在子组件中操作 Pinia store而是通过 props/emits 层层传递?
---
## Day 5Vue Router 路由
**知识点**
- `vue-router`前端路由URL 变化时不刷新页面
- `createRouter({ history: createWebHistory() })`HTML5 History 模式
- `<router-link>`:导航链接(渲染为 `<a>` 标签)
- `<router-view>`:路由出口(匹配的组件渲染在这里)
- 路由懒加载:`() => import('../views/XXX.vue')`
- `meta`:路由元信息(标题、权限等)
- 导航守卫:`beforeEach``afterEach`
- 动态路由:`/user/:id`
**动手 → 理解**
1. 点击导航栏各链接,观察 URL 变化和页面内容,按 F12 Network 面板看是否有网络请求
2.`router/index.js` 中临时把 `createWebHistory` 改为 `createWebHashHistory`,观察 URL 变化(`#` 号出现)
3. 修改某个路由的 `meta.title`,观察浏览器标签变化
4. 在导航守卫中加 `console.log('从', from.path, '到', to.path)`
5. 添加一个 `/user/:name` 动态路由页面
**核心文件**
- `router/index.js` — 路由配置 + 导航守卫
- `components/NavBar.vue``<router-link>` 导航
**思考题**:为什么前端路由要用 History 模式而不是 Hash 模式History 模式上线需要注意什么Nginx 配置)?
---
## Day 6Pinia 状态管理
**知识点**
- 为什么需要状态管理:跨组件/跨页面共享数据
- `defineStore('name', () => { ... })`Setup Store 语法(与 Composition API 一致)
- State`ref()` / `reactive()` 定义状态
- Getters`computed()` 定义派生状态
- Actions普通函数可异步
- `storeToRefs()`:解构时保持响应性
- Store 在 `main.js` 中通过 `app.use(createPinia())` 注入
- 组件中直接 `const store = useXxxStore()` 使用
**动手 → 理解**
1. 打开 `stores/todo.js`,观察 state/getters/actions 的定义方式
2. 在浏览器中操作 Todo打开 Vue DevTools 的 Pinia 面板查看状态变化
3.`CounterView.vue` 中对比Pinia store 的 counter 和本地 ref 的 counter
4.`storeToRefs(todoStore)` 解构 `todos`,验证响应性
5. 练习:新建一个 `theme` store管理暗色/亮色主题切换
**核心文件**
- `stores/counter.js` — 简单 store 示例
- `stores/todo.js` — 完整 CRUD store
- `stores/auth.js` — 认证 Token store
- `main.js``app.use(createPinia())`
**思考题**Pinia 和 Vuex 有什么区别?为什么 Vue 3 官方推荐 Pinia
---
## Day 7Axios 封装与请求拦截
**知识点**
- `axios.create()`:创建实例,配置 baseURL、timeout
- 请求拦截器:自动附加 Token、设置 Content-Type
- 响应拦截器:统一处理 401/403/500
- `Authorization: Bearer <token>`JWT 标准格式
- Vite proxy 配置:开发环境代理 `/api` 到 Spring Boot
- `.env` 环境变量:`VITE_API_BASE_URL`
**动手 → 理解**
1. 打开 `api/http.js`,对照 Week 5 的 `app.js``api()` 函数,对比封装方式
2. 用 DevTools Network 面板观察请求头中是否有 `Authorization`
3. 故意把 token 改错,观察响应拦截器的 401 处理
4. 检查 `vite.config.js` 的 proxy 配置,理解开发环境代理原理
5. 添加 `VITE_API_BASE_URL` 环境变量,修改 `baseURL` 读取环境变量
**核心文件**
- `api/http.js` — Axios 实例 + 拦截器
- `vite.config.js``server.proxy` — 开发代理
- `stores/auth.js` — Token 存储与模拟登录
**思考题**:为什么开发环境需要 Vite proxy而生产环境用 Nginx 反向代理?
---
## Week 6 总结
| 维度 | 掌握内容 |
|------|---------|
| 脚手架 | Vite 创建项目、目录结构、HMR 热更新 |
| 响应式 | ref / reactive / computed / watch |
| 指令 | v-if / v-show / v-for / v-model / v-bind / v-on |
| 组件 | SFC、props / emits、slot、scoped style |
| 路由 | Vue Router、懒加载、导航守卫 |
| 状态 | Pinia Setup Store、storeToRefs |
| 网络 | Axios 封装、拦截器、Vite proxy |
**与 Week 5 的对比**
| | Week 5 前端 | Week 6 前端 |
|------|-----------|-----------|
| 框架 | 原生 HTML + 原生 JS | Vue 3 + Vite |
| 状态管理 | localStorage + DOM 操作 | Pinia 响应式 store |
| 路由 | 无(单页面切换 display | Vue Router History 模式 |
| HTTP | fetch 手写 | Axios 拦截器封装 |
| 组件化 | 无 | SFC + props/emits |
| 开发体验 | 手动刷新 | HMR 热更新 |
**预习 Week 7**:将本项目的 Vue 前端与 Week 5 的 Spring Boot 后端对接,用 Axios 替换模拟登录,实现前后端分离的学生管理系统 v3。