Files
gc-plan/week6/教案.md
2026-04-29 23:45:17 +08:00

227 lines
9.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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。