AI驱动Web_Vue详解
AI 驱动 Web - Vue 详解
本章位置:第三阶段 Java 企业项目 + AI 助手
对应课程:AI 驱动 Web - Vue(第一部分)
前置知识:HTML、CSS、JavaScript、HTTP、RESTful、SpringBoot 请求响应
本章目标:从 Java 后端开发者视角学习 Vue 3,掌握 Vite 项目创建、组件、模板语法、响应式、事件、表单、生命周期、组件通信、Vue Router、Axios、Element Plus、SpringBoot 前后端联调,以及使用 AI 辅助前端开发的正确方式。
建议开发环境:Node.js、npm、VS Code / Cursor、Chrome / Edge、SpringBoot 后端。
一、为什么 Java 后端也必须学 Vue
以前传统 Java Web:
浏览器
↓
Servlet
↓
JSP
↓
服务器生成 HTML
↓
浏览器显示
现在前后端分离项目:
Vue
负责页面
SpringBoot
负责接口
MyBatis
负责数据库
完整流程:
Vue 页面
↓
Axios
↓
HTTP / JSON
↓
SpringBoot Controller
↓
Service
↓
Mapper
↓
MySQL
↓
JSON Response
↓
Vue 更新页面
所以你现在学 Vue,不是为了变成纯前端工程师,而是为了:
能够独立完成前后端项目
能够看懂企业后台前端
能够和 SpringBoot 接口联调
能够修改若依等 Vue 项目
能够让 AI 帮你生成前端后自己看懂和修改
二、Vue 是什么
Vue 是:
渐进式 JavaScript 前端框架
当前我们学习:
Vue 3
Vue 最核心的思想:
数据驱动视图
组件化开发
三、什么叫数据驱动视图
传统 JavaScript:
const count =
document.querySelector(
"#count"
)
count.innerText =
10
需要:
自己找 DOM
自己修改 DOM
Vue:
const count =
ref(
10
)
模板:
<p>
{{ count }}
</p>
当:
count 改变
Vue 自动:
更新页面
四、Vue 核心思想
可以先记住:
数据变化
↓
Vue 响应式系统发现变化
↓
重新计算需要更新的内容
↓
更新 DOM
五、组件化是什么
一个页面不再全部写:
一个巨大 HTML 文件
而是拆成:
Header
Sidebar
UserTable
UserForm
Pagination
LoginForm
每一块:
一个组件
六、组件树
例如后台系统:
App
│
├─ Layout
│ ├─ Sidebar
│ ├─ Header
│ └─ Main
│ └─ UserPage
│ ├─ SearchForm
│ ├─ UserTable
│ └─ UserDialog
这就是:
组件树
七、为什么 Vue 适合 SpringBoot 项目
SpringBoot:
@RestController
返回:
{
"code": "SUCCESS",
"message": "success",
"data": []
}
Vue:
Axios 请求 JSON
↓
拿 data
↓
更新页面
前后端职责清晰。
八、Vue 3 推荐项目工具链
当前新项目推荐:
Vue 3
create-vue
Vite
Vue Router
Pinia
Element Plus
Axios
初学阶段重点:
Vue
Router
Axios
Element Plus
Pinia 后面再系统学习。
九、Vue CLI 为什么暂时不学
老教程经常:
vue create xxx
这是:
Vue CLI
新项目现在更推荐:
create-vue + Vite
所以本课程默认:
不从 Vue CLI 开始
十、什么是 Node.js
Vue 源代码运行在浏览器。
但是前端开发工具:
Vite
npm
构建工具
插件
需要:
Node.js
十一、Node.js 在这里的作用
你可以理解:
JDK
对 Java 开发工具链很重要
Node.js
对现代前端开发工具链很重要
但两者不是完全等价。
十二、npm 是什么
npm:
Node Package Manager
主要负责:
下载前端依赖
管理 package.json
执行脚本
类似 Maven 中:
dependency
plugin command
十三、Maven 和 npm 类比
Maven
pom.xml
npm
package.json
Maven:
mvn package
前端:
npm run build
Maven 本地依赖:
.m2/repository
npm 项目依赖:
node_modules
十四、先检查 Node
Windows PowerShell:
node -v
再:
npm -v
如果都有版本:
安装成功
十五、Node 版本问题
前端工具更新比较快。
如果执行:
npm create vue@latest
提示:
Node version unsupported
不要乱改代码。
直接:
升级 Node.js
并以当前 Vue / Vite 官方要求为准。
十六、创建 Vue 项目
推荐:
npm create vue@latest
然后命令行会让你选择:
Project name
TypeScript
JSX
Vue Router
Pinia
Vitest
ESLint
Prettier
十七、当前学习阶段怎么选
建议初学:
TypeScript
No
JSX
No
Vue Router
Yes
Pinia
可以先 No
Vitest
No
E2E
No
ESLint
Yes
Prettier
可选 Yes
十八、为什么初学先 JavaScript
因为你刚进入 Vue。
如果立刻同时学:
Vue
+
TypeScript
+
Pinia
+
Router
+
ESLint
容易:
知识叠太多
先使用:
Vue 3 + JavaScript
理解核心。
十九、以后要不要学 TypeScript
要。
企业 Vue 项目非常常见:
Vue 3 + TypeScript
但建议:
先会 Vue
再升级 TS
二十、进入项目
例如:
cd vue-demo
安装:
npm install
启动:
npm run dev
二十一、Vite 开发服务器
启动后通常显示类似:
Local:
http://localhost:5173
浏览器访问:
http://localhost:5173
二十二、为什么不是 8080
SpringBoot 常见:
8080
Vite 开发服务器常见:
5173
所以前后端开发时:
前端 5173
后端 8080
二十三、这会产生什么
浏览器会认为:
不同 Origin
因为端口不同。
于是可能出现:
CORS
跨域
后面专门处理。
二十四、Vue 项目目录
典型:
vue-demo
│
├─ node_modules
├─ public
├─ src
│ ├─ assets
│ ├─ components
│ ├─ router
│ ├─ views
│ ├─ App.vue
│ └─ main.js
│
├─ index.html
├─ package.json
├─ vite.config.js
└─ package-lock.json
二十五、package.json
类似 Maven:
pom.xml
里面定义:
项目名称
依赖
开发依赖
npm scripts
二十六、dependencies
运行项目需要:
Vue
Vue Router
Axios
Element Plus
等。
二十七、devDependencies
开发/构建工具:
Vite
ESLint
插件
通常在:
devDependencies
二十八、npm install 做什么
读取:
package.json
package-lock.json
然后把依赖安装到:
node_modules
二十九、不要提交 node_modules
因为:
非常大
可以重新安装
Git 一般:
忽略 node_modules
三十、package-lock.json
它用来:
锁定实际解析的依赖版本
企业项目通常应该:
提交 Git
这样团队安装更稳定。
三十一、npm run dev
package.json 里类似:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
}
执行:
npm run dev
实际上执行:
vite
三十二、npm run build
npm run build
生成生产静态资源:
dist
三十三、dist 是什么
生产构建结果。
里面通常:
index.html
assets/*.js
assets/*.css
最终可以交给:
Nginx
部署。
三十四、main.js
Vue 应用入口。
典型:
import {
createApp
} from "vue"
import App
from "./App.vue"
createApp(
App
).mount(
"#app"
)
三十五、createApp
创建:
Vue Application
三十六、App.vue
根组件:
整个 Vue 组件树的根
三十七、mount(“#app”)
把 Vue 应用挂载到:
<div id="app"></div>
三十八、index.html
Vite 项目中:
index.html
是非常重要的入口文件。
里面通常:
<div id="app"></div>
三十九、.vue 文件是什么
.vue:
Single File Component
中文:
单文件组件
四十、Vue 单文件组件三部分
典型:
<script setup>
</script>
<template>
</template>
<style scoped>
</style>
四十一、template
负责:
页面结构
类似:
HTML
四十二、script
负责:
JavaScript 逻辑
数据
函数
生命周期
四十三、style
负责:
CSS 样式
四十四、script setup
Vue 3 推荐常见写法:
<script setup>
</script>
相比旧 Options API:
更简洁
本课程主要使用:
Composition API + script setup
四十五、第一个 Vue 组件
<script setup>
const title =
"学生管理"
</script>
<template>
<h1>
{{ title }}
</h1>
</template>
四十六、插值表达式
{{ title }}
叫:
Mustache interpolation
插值表达式
用于显示数据。
四十七、插值可以写简单表达式
例如:
{{ age + 1 }}
{{ username.toUpperCase() }}
四十八、不要在模板写复杂逻辑
不推荐:
{{ veryLongComplexExpression... }}
复杂逻辑:
computed
函数
中处理。
四十九、响应式数据 ref
import {
ref
} from "vue"
const count =
ref(
0
)
五十、为什么要 ref
普通变量:
let count =
0
Vue 不一定能按响应式方式追踪。
使用:
ref
Vue 能:
追踪变化
更新视图
五十一、修改 ref
JavaScript 中:
count.value++
五十二、模板中为什么不用 .value
模板:
{{ count }}
Vue 会:
自动解包 ref
所以不用:
{{ count.value }}
五十三、按钮事件
<script setup>
import {
ref
} from "vue"
const count =
ref(
0
)
const add =
() => {
count.value++
}
</script>
<template>
<button
@click="add"
>
{{ count }}
</button>
</template>
五十四、@click
等价完整形式:
v-on:click
简写:
@click
五十五、v-bind
动态绑定属性:
<img
v-bind:src="avatarUrl"
/>
简写:
<img
:src="avatarUrl"
/>
五十六、冒号 :
Vue 中:
:
经常表示:
v-bind
五十七、v-if
条件渲染:
<p
v-if="score >= 60"
>
及格
</p>
五十八、v-else
<p
v-if="score >= 60"
>
及格
</p>
<p
v-else
>
不及格
</p>
五十九、v-else-if
<p
v-if="score >= 90"
>
优秀
</p>
<p
v-else-if="score >= 60"
>
及格
</p>
<p
v-else
>
不及格
</p>
六十、v-show
<div
v-show="visible"
>
内容
</div>
六十一、v-if 和 v-show 区别
v-if:
条件为 false
DOM 可能直接不存在
v-show:
DOM 仍存在
通过 CSS display 控制
六十二、什么时候用 v-if
条件:
很少切换
可以:
v-if
六十三、什么时候用 v-show
元素:
频繁显示/隐藏
可考虑:
v-show
六十四、v-for
列表渲染:
<li
v-for="student in students"
:key="student.id"
>
{{ student.name }}
</li>
六十五、v-for index
<tr
v-for="(student, index) in students"
:key="student.id"
>
<td>
{{ index + 1 }}
</td>
<td>
{{ student.name }}
</td>
</tr>
六十六、为什么要 key
Vue 更新列表时:
需要识别每一项身份
推荐:
数据库主键
例如:
:key="student.id"
六十七、不推荐 index 作为 key
如果列表会:
插入
删除
排序
index 会变化。
容易造成:
组件状态复用错误
六十八、v-model
双向绑定:
<input
v-model="username"
/>
六十九、v-model 完整例子
<script setup>
import {
ref
} from "vue"
const username =
ref(
""
)
</script>
<template>
<input
v-model="username"
/>
<p>
{{ username }}
</p>
</template>
七十、什么叫双向绑定
输入框变化:
→ username 变化
username 变化:
→ 输入框显示变化
七十一、v-model.number
<input
v-model.number="age"
/>
帮助:
转为数字
七十二、v-model.trim
<input
v-model.trim="username"
/>
自动:
去掉首尾空格
七十三、reactive
除了 ref:
import {
reactive
} from "vue"
const form =
reactive({
username: "",
age: null
})
七十四、ref 和 reactive 怎么选
初学建议:
简单值
ref
对象表单
reactive
例如:
loading
ref(false)
keyword
ref("")
form
reactive({...})
七十五、reactive 修改
form.username =
"admin"
不需要:
.value
七十六、不要直接替换 reactive 对象
例如:
form =
newForm
如果 form 用 const:
本身也不能重新赋值
更重要的是:
可能破坏响应式引用
通常:
Object.assign(
form,
newForm
)
七十七、computed
计算属性:
import {
computed,
ref
} from "vue"
const firstName =
ref(
"三"
)
const lastName =
ref(
"张"
)
const fullName =
computed(
() =>
lastName.value
+
firstName.value
)
模板:
{{ fullName }}
七十八、computed 适合什么
从已有响应式数据:
推导新数据
例如:
总价
过滤后的列表
是否有权限
全名
七十九、computed 和普通函数区别
computed:
有缓存
依赖没变化时可复用结果
普通函数:
每次调用重新执行
八十、watch
监听数据变化:
watch(
keyword,
(
newValue,
oldValue
) => {
console.log(
newValue
)
}
)
八十一、watch 适合什么
当某数据变化后:
执行副作用
例如:
重新请求接口
写 localStorage
触发日志
八十二、computed 和 watch 区别
computed:
计算一个结果
watch:
数据变了
执行一件事
八十三、watchEffect
watchEffect(
() => {
console.log(
keyword.value
)
}
)
Vue 会自动追踪:
里面使用的响应式依赖
八十四、不要滥用 watch
如果只是:
a + b
应该:
computed
而不是:
watch a
再手动赋值 c
八十五、事件传参数
<button
@click="deleteStudent(student.id)"
>
删除
</button>
八十六、事件对象
<button
@click="handleClick"
>
点击
</button>
JavaScript:
const handleClick =
event => {
console.log(
event
)
}
八十七、事件修饰符
例如:
<form
@submit.prevent="submit"
>
.prevent:
阻止默认行为
八十八、.stop
@click.stop
阻止:
事件冒泡
八十九、组件是什么
Vue 组件:
可复用 UI 单元
例如:
UserDialog.vue
StudentTable.vue
SearchBar.vue
九十、创建组件
例如:
src/components/UserCard.vue
九十一、UserCard.vue
<script setup>
defineProps({
username: {
type: String,
required: true
}
})
</script>
<template>
<div>
用户:
{{ username }}
</div>
</template>
九十二、父组件使用
<script setup>
import UserCard
from "@/components/UserCard.vue"
</script>
<template>
<UserCard
username="admin"
/>
</template>
九十三、Props
Props:
父组件
↓
给子组件传数据
九十四、Props 单向数据流
子组件不应该:
直接修改父组件传来的 prop
应该:
通知父组件修改
九十五、emit
子组件:
向父组件发送事件
九十六、defineEmits
const emit =
defineEmits([
"delete"
])
const handleDelete =
() => {
emit(
"delete"
)
}
九十七、父组件监听子事件
子:
<button
@click="handleDelete"
>
删除
</button>
父:
<UserCard
@delete="deleteUser"
/>
九十八、组件通信基本规则
父 → 子
Props
子 → 父
Emit
九十九、插槽 slot
子组件:
<div class="card">
<slot></slot>
</div>
父:
<MyCard>
<h2>
用户管理
</h2>
</MyCard>
一百、slot 的作用
让父组件:
向子组件插入内容
适合:
Dialog
Card
Layout
一百零一、生命周期
组件不是:
永远存在
它会经历:
创建
挂载
更新
卸载
一百零二、onMounted
import {
onMounted
} from "vue"
onMounted(
() => {
loadStudents()
}
)
一百零三、onMounted 常用场景
页面打开时:
请求列表
初始化图表
读取数据
一百零四、onUnmounted
组件卸载时:
onUnmounted(
() => {
// 清理
}
)
一百零五、为什么需要清理
例如:
定时器
WebSocket
事件监听器
如果不清理:
可能内存泄漏
一百零六、常用生命周期
Composition API 常见:
onMounted
onUpdated
onUnmounted
onBeforeMount
onBeforeUnmount
初学重点:
onMounted
onUnmounted
一百零七、页面请求列表例子
<script setup>
import {
onMounted,
ref
} from "vue"
const students =
ref([])
const loadStudents =
async () => {
}
onMounted(
() => {
loadStudents()
}
)
</script>
一百零八、Promise
Axios 请求是:
异步操作
常返回:
Promise
一百零九、async / await
推荐:
const loadStudents =
async () => {
const response =
await axios.get(
"/api/students"
)
students.value =
response.data.data
}
一百一十、try/catch
const loadStudents =
async () => {
try {
const response =
await axios.get(
"/api/students"
)
students.value =
response.data.data
} catch (
error
) {
console.error(
error
)
}
}
一百一十一、loading
请求时通常:
const loading =
ref(
false
)
一百一十二、完整 loading
const loadStudents =
async () => {
loading.value =
true
try {
// request
} finally {
loading.value =
false
}
}
一百一十三、为什么 finally
无论:
成功
失败
都要:
关闭 loading
一百一十四、Vue Router 是什么
Vue Router:
Vue 官方路由
用于:
单页应用页面切换
一百一十五、SPA
SPA:
Single Page Application
中文:
单页应用
一百一十六、单页应用不是只有一个页面
它的意思:
通常只有一个 HTML 入口
内部页面:
由 JavaScript Router 切换组件
一百一十七、传统页面
/users.html
/roles.html
/login.html
每次:
服务器返回新 HTML
一百一十八、Vue SPA
浏览器:
加载 index.html
后续:
/login
/users
/roles
由:
Vue Router
切换组件。
一百一十九、Router 配置
import {
createRouter,
createWebHistory
} from "vue-router"
import LoginView
from "@/views/LoginView.vue"
import UserView
from "@/views/UserView.vue"
const router =
createRouter({
history:
createWebHistory(),
routes: [
{
path: "/login",
component:
LoginView
},
{
path: "/users",
component:
UserView
}
]
})
export default router
一百二十、main.js 注册 Router
import {
createApp
} from "vue"
import App
from "./App.vue"
import router
from "./router"
const app =
createApp(
App
)
app.use(
router
)
app.mount(
"#app"
)
一百二十一、router-view
App.vue:
<router-view />
表示:
当前路由组件
显示在这里
一百二十二、router-link
<router-link
to="/users"
>
用户管理
</router-link>
一百二十三、编程式跳转
import {
useRouter
} from "vue-router"
const router =
useRouter()
router.push(
"/users"
)
一百二十四、带参数路由
{
path:
"/users/:id",
component:
UserDetailView
}
访问:
/users/10
一百二十五、获取路由参数
import {
useRoute
} from "vue-router"
const route =
useRoute()
const id =
route.params.id
一百二十六、query 参数
访问:
/users?page=1&keyword=admin
获取:
route.query.page
route.query.keyword
一百二十七、params 和 query 对应后端
Vue Router:
/users/10
params
SpringBoot:
@PathVariable
Vue:
/users?page=1
query
SpringBoot:
@RequestParam
一百二十八、路由守卫
可以控制:
页面进入前做检查
例如:
没有 Token
→ 去登录
一百二十九、beforeEach
router.beforeEach(
(
to,
from,
next
) => {
const token =
localStorage.getItem(
"token"
)
if (
!token
&&
to.path !== "/login"
) {
next(
"/login"
)
return
}
next()
}
)
一百三十、注意前端路由守卫不是安全边界
用户可以:
绕过前端
直接 Postman 请求后端
所以真正安全:
必须后端认证授权
一百三十一、localStorage
浏览器存储:
localStorage.setItem(
"token",
token
)
读取:
localStorage.getItem(
"token"
)
删除:
localStorage.removeItem(
"token"
)
一百三十二、Token 存 localStorage 有安全风险吗
有。
如果页面发生:
XSS
恶意脚本可能读取 Token。
更安全的认证方案还会考虑:
HttpOnly Cookie
SameSite
CSRF
当前学习项目先理解:
Token 流程
一百三十三、Axios 是什么
Axios:
HTTP Client
前端常用它:
调用 SpringBoot API
一百三十四、安装 Axios
npm install axios
一百三十五、最简单 GET
import axios
from "axios"
const response =
await axios.get(
"http://localhost:8080/api/users"
)
一百三十六、response
通常:
response.data
才是:
后端 JSON Body
一百三十七、假设后端返回
{
"code": "SUCCESS",
"message": "success",
"data": [
{
"id": 1,
"username": "admin"
}
]
}
Axios:
response.data.code
response.data.message
response.data.data
一百三十八、Axios POST
await axios.post(
"/api/users",
{
username:
"admin2",
password:
"123456"
}
)
一百三十九、POST JSON 对应 SpringBoot
前端:
axios.post(
"/api/users",
form
)
后端:
@PostMapping
public Result<?> create(
@RequestBody
UserCreateDTO dto
)
一百四十、Axios PUT
await axios.put(
"/api/users/10",
{
nickname:
"张三"
}
)
一百四十一、Axios DELETE
await axios.delete(
"/api/users/10"
)
一百四十二、Axios Query 参数
await axios.get(
"/api/users",
{
params: {
pageNum: 1,
pageSize: 10,
keyword: ""
}
}
)
一百四十三、推荐封装 Axios
不要所有页面:
重复写 baseURL
Token
401
403
建议:
src/utils/request.js
一百四十四、request.js
import axios
from "axios"
const request =
axios.create({
baseURL:
"/api",
timeout:
10000
})
export default request
一百四十五、baseURL
如果调用:
request.get(
"/users"
)
最终:
/api/users
一百四十六、请求拦截器
request.interceptors.request.use(
config => {
const token =
localStorage.getItem(
"token"
)
if (
token
) {
config.headers.Authorization =
`Bearer ${token}`
}
return config
}
)
一百四十七、为什么 Request Interceptor 很重要
以后每个请求自动:
带 Token
不需要每个 API:
手工写 Header
一百四十八、响应拦截器
request.interceptors.response.use(
response => {
return response.data
},
error => {
return Promise.reject(
error
)
}
)
一百四十九、统一处理 401
if (
error.response?.status
===
401
) {
localStorage.removeItem(
"token"
)
window.location.href =
"/login"
}
一百五十、统一处理 403
if (
error.response?.status
===
403
) {
// 提示无权限
}
一百五十一、不要把 401 和 403 都跳登录
401:
登录失效
可以:
跳登录
403:
已经登录
但无权限
应该:
提示无权限
一百五十二、API 文件
建议:
src/api
例如:
user.js
auth.js
role.js
一百五十三、auth.js
import request
from "@/utils/request"
export const login =
data => {
return request.post(
"/auth/login",
data
)
}
export const getMe =
() => {
return request.get(
"/auth/me"
)
}
一百五十四、user.js
import request
from "@/utils/request"
export const getUserPage =
params => {
return request.get(
"/users",
{
params
}
)
}
export const createUser =
data => {
return request.post(
"/users",
data
)
}
export const updateUser =
(
id,
data
) => {
return request.put(
`/users/${id}`,
data
)
}
export const deleteUser =
id => {
return request.delete(
`/users/${id}`
)
}
一百五十五、为什么 API 单独封装
页面只关心:
我要加载用户
我要删除用户
而不是关心:
Axios 配置细节
一百五十六、推荐前端分层
View / Component
↓
API Module
↓
request.js
↓
Axios
↓
SpringBoot
一百五十七、Element Plus 是什么
Element Plus:
Vue 3 常用桌面端 UI 组件库
非常适合:
后台管理系统
一百五十八、安装 Element Plus
npm install element-plus
一百五十九、完整引入
学习阶段可以:
import ElementPlus
from "element-plus"
import "element-plus/dist/index.css"
app.use(
ElementPlus
)
一百六十、为什么学习阶段先完整引入
优点:
配置简单
容易理解
少踩自动导入配置坑
项目成熟后再:
按需自动导入
一百六十一、Element Plus 常用组件
后台项目必须会:
el-button
el-input
el-form
el-form-item
el-table
el-table-column
el-dialog
el-select
el-option
el-pagination
el-message
el-message-box
el-menu
el-card
el-tag
一百六十二、el-button
<el-button
type="primary"
>
新增
</el-button>
一百六十三、el-input
<el-input
v-model="query.keyword"
placeholder="请输入用户名"
/>
一百六十四、el-form
<el-form
:model="form"
>
<el-form-item
label="用户名"
>
<el-input
v-model="form.username"
/>
</el-form-item>
</el-form>
一百六十五、表单验证 rules
const rules = {
username: [
{
required: true,
message: "请输入用户名",
trigger: "blur"
}
]
}
一百六十六、el-form 绑定 rules
<el-form
ref="formRef"
:model="form"
:rules="rules"
>
一百六十七、提交前校验
await formRef.value.validate()
校验通过:
再调用后端
一百六十八、前端校验不是安全边界
后端仍然需要:
@Valid
因为用户可以:
绕过前端
直接调用 API
一百六十九、el-table
<el-table
:data="users"
>
<el-table-column
prop="username"
label="用户名"
/>
<el-table-column
prop="nickname"
label="昵称"
/>
</el-table>
一百七十、操作列
<el-table-column
label="操作"
>
<template
#default="{ row }"
>
<el-button
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
type="danger"
@click="handleDelete(row)"
>
删除
</el-button>
</template>
</el-table-column>
一百七十一、#default
这是:
具名/作用域插槽
Element Plus 会把当前:
row
传给模板。
一百七十二、el-dialog
<el-dialog
v-model="dialogVisible"
title="新增用户"
>
...
</el-dialog>
一百七十三、Dialog 状态
const dialogVisible =
ref(
false
)
打开:
dialogVisible.value =
true
一百七十四、新增/编辑共用 Dialog
常见:
form.id
为空
→ 新增
form.id
有值
→ 编辑
一百七十五、推荐更清晰
可以加:
const dialogMode =
ref(
"create"
)
取值:
create
edit
一百七十六、为什么显式 mode 更清晰
比通过:
id 是否为空
猜业务状态:
更直观
一百七十七、el-message
import {
ElMessage
} from "element-plus"
ElMessage.success(
"保存成功"
)
一百七十八、错误消息
ElMessage.error(
"保存失败"
)
一百七十九、删除确认
await ElMessageBox.confirm(
"确认删除该用户吗?",
"提示",
{
type: "warning"
}
)
一百八十、分页组件
<el-pagination
v-model:current-page="query.pageNum"
v-model:page-size="query.pageSize"
:total="total"
@current-change="loadUsers"
@size-change="loadUsers"
/>
一百八十一、分页数据
const query =
reactive({
pageNum: 1,
pageSize: 10,
keyword: ""
})
const total =
ref(
0
)
一百八十二、后端分页响应
例如:
{
"code": "SUCCESS",
"data": {
"records": [],
"total": 100,
"pageNum": 1,
"pageSize": 10
}
}
前端:
users.value =
result.data.records
total.value =
result.data.total
一百八十三、完整用户列表页面思路
UserView.vue
│
├─ 查询表单
├─ 新增按钮
├─ el-table
├─ 操作按钮
├─ el-pagination
└─ UserDialog
一百八十四、UserView 数据
const loading =
ref(
false
)
const users =
ref([])
const total =
ref(
0
)
const query =
reactive({
pageNum: 1,
pageSize: 10,
keyword: ""
})
一百八十五、加载用户
const loadUsers =
async () => {
loading.value =
true
try {
const result =
await getUserPage(
query
)
users.value =
result.data.records
total.value =
result.data.total
} finally {
loading.value =
false
}
}
一百八十六、搜索
const handleSearch =
() => {
query.pageNum =
1
loadUsers()
}
一百八十七、为什么搜索重置第一页
如果当前:
第 8 页
然后输入一个只有:
1 页结果
如果不回第 1 页:
可能显示空数据
一百八十八、重置搜索
const resetSearch =
() => {
query.keyword =
""
query.pageNum =
1
loadUsers()
}
一百八十九、新增用户
const openCreate =
() => {
dialogMode.value =
"create"
Object.assign(
form,
{
id: null,
username: "",
password: "",
nickname: ""
}
)
dialogVisible.value =
true
}
一百九十、编辑用户
const openEdit =
row => {
dialogMode.value =
"edit"
Object.assign(
form,
{
id:
row.id,
username:
row.username,
nickname:
row.nickname,
password:
""
}
)
dialogVisible.value =
true
}
一百九十一、提交
const submit =
async () => {
await formRef.value.validate()
if (
dialogMode.value
===
"create"
) {
await createUser(
form
)
} else {
await updateUser(
form.id,
form
)
}
ElMessage.success(
"保存成功"
)
dialogVisible.value =
false
loadUsers()
}
一百九十二、删除
const handleDelete =
async row => {
await ElMessageBox.confirm(
`确认删除 ${row.username} 吗?`,
"提示",
{
type:
"warning"
}
)
await deleteUser(
row.id
)
ElMessage.success(
"删除成功"
)
loadUsers()
}
一百九十三、为什么删除后重新加载列表
数据库已经:
删除
前端旧数组:
仍可能包含该用户
重新请求:
保证和后端一致
一百九十四、也可以前端直接 remove 吗
可以。
但后台 CRUD 初学时:
操作成功后重新加载
最稳。
一百九十五、登录页面
核心数据:
const form =
reactive({
username: "",
password: ""
})
一百九十六、登录提交
const handleLogin =
async () => {
const result =
await login(
form
)
localStorage.setItem(
"token",
result.data.token
)
router.push(
"/"
)
}
一百九十七、登录后权限
后端可能返回:
roles
permissions
前端可以保存:
Pinia
或者学习阶段:
内存 ref / localStorage
一百九十八、为什么权限不建议全部长期写 localStorage
权限:
可能随时变
更合理:
页面刷新后
带 Token 请求 /auth/me
重新获得:
当前权限
一百九十九、前端菜单权限
假设:
permissions.value.includes(
"user:list"
)
才显示:
用户管理
二百、按钮权限
<el-button
v-if="
permissions.includes(
'user:add'
)
"
>
新增
</el-button>
二百零一、再次强调
这个:
只是 UI 控制
后端仍然必须:
user:add
权限校验。
二百零二、SpringBoot 前后端联调
前端:
http://localhost:5173
后端:
http://localhost:8080
直接请求:
可能跨域
二百零三、什么是同源
Origin 包括:
协议
域名
端口
只要有一项不同:
不同源
二百零四、5173 和 8080
端口不同
所以:
不同 Origin
二百零五、解决方式 1:后端 CORS
SpringBoot:
@Configuration
public class WebConfig
implements WebMvcConfigurer {
@Override
public void addCorsMappings(
CorsRegistry registry
) {
registry
.addMapping(
"/api/**"
)
.allowedOrigins(
"http://localhost:5173"
)
.allowedMethods(
"GET",
"POST",
"PUT",
"DELETE",
"OPTIONS"
);
}
}
二百零六、解决方式 2:Vite Proxy
开发阶段更常用:
Vite 代理
二百零七、vite.config.js
import {
defineConfig
} from "vite"
import vue
from "@vitejs/plugin-vue"
export default defineConfig({
plugins: [
vue()
],
server: {
proxy: {
"/api": {
target:
"http://localhost:8080",
changeOrigin:
true
}
}
}
})
二百零八、代理以后
浏览器请求:
http://localhost:5173/api/users
Vite:
转发到
http://localhost:8080/api/users
二百零九、前端 Axios baseURL
可以:
baseURL:
"/api"
不必硬编码:
http://localhost:8080
二百一十、为什么推荐开发代理
前端代码:
更接近生产部署路径
也减少:
开发跨域配置
二百一十一、生产环境怎么办
生产:
Nginx
可以:
/
→ Vue 静态文件
/api
→ SpringBoot
浏览器看起来:
同一个域名
二百一十二、典型生产架构
Browser
↓
Nginx
├─ /
│ → Vue dist
│
└─ /api
→ SpringBoot:8080
二百一十三、这就是前后端分离部署
Vue:
构建为静态文件
SpringBoot:
运行 API 服务
Nginx:
统一入口
二百一十四、常见错误:npm command not found
说明:
Node/npm 未安装
或者:
PATH 未生效
检查:
node -v
npm -v
二百一十五、常见错误:npm install 很慢
原因:
网络
registry
代理
不要一上来:
反复删除所有项目
先确认:
网络
npm registry
二百一十六、常见错误:node_modules 损坏
可以尝试:
关闭 dev server
删除:
node_modules
然后:
npm install
但不要:
遇到任何错误都这么做
二百一十七、常见错误:页面空白
检查浏览器:
F12
→ Console
常见:
JS 报错
组件 import 错
Router 错
变量未定义
二百一十八、常见错误:组件找不到
检查:
import 路径
文件名大小写
.vue 后缀
alias @
二百一十九、@ 别名
很多 Vite Vue 项目配置:
@
→ src
于是:
import UserView
from "@/views/UserView.vue"
二百二十、常见错误:ref 忘 .value
JavaScript:
loading =
true
错误。
如果:
const loading =
ref(false)
应该:
loading.value =
true
二百二十一、模板中不用 .value
模板:
{{ loading }}
不是:
{{ loading.value }}
二百二十二、常见错误:reactive 解构丢响应式
例如:
const state =
reactive({
count: 0
})
const {
count
} =
state
直接解构:
可能失去预期响应式连接
可以:
toRefs
或:
直接 state.count
二百二十三、初学避免复杂解构
先:
state.count
最清楚。
二百二十四、常见错误:v-for 没 key
会警告:
列表渲染缺少 key
推荐:
:key="row.id"
二百二十五、常见错误:v-if 和 v-for 写同元素
不推荐把:
v-if
v-for
复杂地放同一个节点。
建议:
computed 先过滤
二百二十六、常见错误:Axios 得到 undefined
后端:
{
"data": {
"records": []
}
}
如果 response interceptor 已经:
return response.data
页面再写:
result.data.data.records
就多了一层。
二百二十七、必须统一 Axios 返回约定
例如 request.js:
return response.data
那么页面:
result.data
表示后端 Result 的:
data
二百二十八、不要不同 API 不同返回方式
否则:
有的 response.data.data
有的 result.data
有的 result
很乱。
二百二十九、常见错误:SpringBoot 404
前端请求:
/api/users
后端:
@RequestMapping(
"/users"
)
如果后端没有:
/api
前缀,
就不匹配。
二百三十、先看 Network
浏览器:
F12
→ Network
查看:
Request URL
Method
Status
Request Payload
Response
二百三十一、前后端联调排错顺序
1. 前端是否发请求
2. Request URL
3. HTTP Method
4. Query / Body
5. Content-Type
6. SpringBoot 是否收到
7. Controller Mapping
8. Service
9. Mapper / SQL
10. Response JSON
11. Vue 是否正确取 data
二百三十二、常见错误:400
检查:
JSON 字段
类型
@Valid
@RequestBody
二百三十三、常见错误:401
检查:
Token 是否保存
Request Interceptor
Authorization Header
Bearer 空格
Token 是否过期
二百三十四、常见错误:403
说明:
大概率已经登录
检查:
permission code
角色权限关系
后端鉴权
二百三十五、常见错误:415
检查:
Content-Type
Axios POST 对象通常:
会按 JSON 发送
如果自己错误配置:
可能导致 415
二百三十六、常见错误:CORS
浏览器 Console 出现:
blocked by CORS policy
说明:
请求被浏览器跨域策略拦截
二百三十七、CORS 不是后端业务异常
SpringBoot 可能:
接口本身正常
但浏览器:
不允许前端读取响应
二百三十八、Postman 为什么没 CORS
CORS 主要是:
浏览器安全机制
Postman:
不受浏览器同源策略约束
所以常见:
Postman 成功
浏览器失败
二百三十九、这种情况优先查什么
CORS
Vite Proxy
二百四十、环境变量
Vite 项目可以:
.env.development
.env.production
二百四十一、Vite 环境变量
客户端可访问变量通常需要:
VITE_
前缀。
例如:
VITE_API_BASE_URL
二百四十二、读取
import.meta.env
.VITE_API_BASE_URL
二百四十三、不要把 Secret 放 VITE_ 环境变量
因为:
前端最终代码发给浏览器
浏览器用户:
可以看到
所以不能放:
数据库密码
JWT 私钥
云 SecretKey
二百四十四、前端不存在真正的 Secret
只要打包到客户端:
用户就有机会查看
安全密钥:
必须放后端
二百四十五、AI 驱动 Web 是什么意思
这里不是:
让 AI 完全替你开发
而是:
利用 AI 提高前端开发效率
二百四十六、AI 适合做什么
例如:
根据接口文档生成 API 封装
根据 DTO 生成表单
根据字段生成 Element Plus 表格
排查 Console 报错
解释 Vue 代码
重构重复组件
生成 CRUD 页面初稿
二百四十七、AI 不适合直接盲信什么
尤其:
依赖版本
过时 API
不存在的组件属性
错误的 Vue2 写法
错误的 Vue3 写法混用
安全配置
二百四十八、AI 生成 Vue 代码后第一步
确认:
Vue 2 还是 Vue 3
本课程:
Vue 3
二百四十九、Vue 2 / Vue 3 容易混淆
老代码:
new Vue(...)
Vue.prototype
Options API 老写法
新项目主要:
createApp
script setup
Composition API
二百五十、给 AI 的提示词要包含项目上下文
例如:
技术栈:
Vue3 + Vite + JavaScript + Element Plus + Axios
后端:
SpringBoot RESTful
统一响应:
{
code,
message,
data
}
要求:
使用 script setup
不要使用 Vue2 API
二百五十一、AI 生成 CRUD 页面提示词示例
为 Vue3 + Vite + Element Plus 项目创建用户管理页面。
后端接口:
GET /api/users
POST /api/users
PUT /api/users/{id}
DELETE /api/users/{id}
分页参数:
pageNum
pageSize
keyword
响应:
{
code,
message,
data: {
records,
total
}
}
要求:
使用 <script setup>
使用 Axios 已封装 request.js
页面包含搜索、重置、新增、编辑、删除和分页。
二百五十二、为什么把接口文档给 AI
如果只说:
帮我做用户管理
AI 会:
自己猜字段
自己猜接口
自己猜响应
很容易和后端:
对不上
二百五十三、AI 驱动开发正确顺序
先有数据库/API 设计
↓
后端接口跑通
↓
把接口文档给 AI
↓
AI 生成前端初稿
↓
自己运行
↓
F12 Network 验证
↓
修正
二百五十四、不要同时让 AI 改全项目
初学时最好:
一个页面
一个功能
一个报错
逐步修改。
二百五十五、为什么
一次改几十个文件:
你无法判断错误来源
二百五十六、Cursor 中使用 AI 的建议
每次给上下文:
当前文件
后端接口
项目目录
报错信息
期望行为
不要只说:
不能用了,修一下
二百五十七、错误信息要完整
最好提供:
浏览器 Console
Network Response
SpringBoot Console
三部分。
二百五十八、AI 排错最有价值的输入
例如:
Request URL:
http://localhost:5173/api/users
Status:
403
Response:
{
"code": "FORBIDDEN"
}
当前 token 已存在
比:
页面不行
有效很多。
二百五十九、Vue 项目推荐目录
src
│
├─ api
│ ├─ auth.js
│ ├─ user.js
│ └─ role.js
│
├─ assets
│
├─ components
│
├─ layout
│
├─ router
│
├─ stores
│
├─ utils
│ └─ request.js
│
├─ views
│ ├─ login
│ ├─ user
│ └─ role
│
├─ App.vue
└─ main.js
二百六十、views 和 components 区别
views:
路由页面
components:
可复用组件
二百六十一、例如
views/user/UserView.vue
是:
用户管理整页
components/UserDialog.vue
是:
可复用弹窗
二百六十二、utils
放:
通用工具
例如:
request.js
date.js
storage.js
二百六十三、api
放:
后端接口函数
二百六十四、router
放:
路由表
路由守卫
二百六十五、stores
后面使用 Pinia:
用户状态
权限
全局设置
二百六十六、Pinia 是什么
Vue 3 推荐状态管理方案:
Pinia
适合管理:
跨组件共享状态
例如:
当前登录用户
权限
主题
菜单
二百六十七、什么时候不需要 Pinia
如果数据只在:
一个页面
使用。
就用:
ref / reactive
不要什么都放全局。
二百六十八、状态管理原则
能局部
就局部
确实多个页面共享
再全局
二百六十九、Vue DevTools
建议浏览器安装:
Vue DevTools
可以查看:
组件树
Props
响应式状态
调试很方便。
二百七十、Chrome DevTools 必须掌握
至少:
Console
Network
Elements
Application
二百七十一、Console
看:
JavaScript Error
Vue Warning
二百七十二、Network
看:
HTTP 请求
这是前后端联调最重要。
二百七十三、Application
可以看:
localStorage
sessionStorage
Cookie
二百七十四、Elements
看:
最终 DOM
CSS
二百七十五、前端学习不要只看页面效果
你要同时会看:
代码
Console
Network
状态
二百七十六、一个完整 CRUD 请求流
点击:
查询
↓
handleSearch()
↓
getUserPage(query)
↓
request.js
↓
Axios
↓
GET /api/users
↓
Vite Proxy
↓
SpringBoot
↓
UserController
↓
UserService
↓
UserMapper
↓
MySQL
↓
Result<PageResult<UserVO>>
↓
Axios Response
↓
users.value
↓
el-table 自动刷新
二百七十七、这张流程必须记住
事件
↓
函数
↓
API
↓
Axios
↓
HTTP
↓
SpringBoot
↓
JSON
↓
响应式数据
↓
Vue DOM
二百七十八、练习 1:计数器
要求:
count
+
-
reset
使用:
ref
@click
二百七十九、练习 2:登录表单
使用:
reactive
v-model
el-form
rules
字段:
username
password
二百八十、练习 3:学生列表
先不用后端。
写:
const students =
ref([
{
id: 1,
name: "张三"
}
])
使用:
v-for
二百八十一、练习 4:Element Plus Table
把学生数组:
渲染为 el-table
二百八十二、练习 5:搜索
使用:
keyword
+
computed
本地过滤学生。
二百八十三、练习 6:Dialog
点击:
新增
打开:
el-dialog
二百八十四、练习 7:Vue Router
创建:
/login
/users
/roles
三个页面。
二百八十五、练习 8:Axios GET
SpringBoot 创建:
GET /api/users
Vue:
加载列表
二百八十六、练习 9:Axios POST
创建:
新增用户
前端 JSON:
→ @RequestBody
二百八十七、练习 10:Vite Proxy
配置:
/api
→ localhost:8080
前端不再写:
完整后端 URL
二百八十八、练习 11:Request Interceptor
登录后:
localStorage token
请求自动:
Authorization Bearer
二百八十九、练习 12:401
清 Token:
访问用户页面
后端返回:
401
前端自动:
跳登录
二百九十、练习 13:403
用普通用户 Token:
调用删除接口
观察:
403
前端:
提示无权限
二百九十一、练习 14:按钮权限
有:
user:add
才显示:
新增按钮
二百九十二、练习 15:分页
SpringBoot:
pageNum
pageSize
Vue:
el-pagination
完成联调。
二百九十三、练习 16:完整 User CRUD
最终完成:
搜索
分页
新增
编辑
删除
权限按钮
loading
消息提示
二百九十四、必须掌握 Vue 基础
createApp
SFC
script setup
template
ref
reactive
computed
watch
v-if
v-show
v-for
v-model
v-bind
v-on
二百九十五、必须掌握组件
Props
Emit
Slot
Component
Lifecycle
二百九十六、必须掌握 Router
createRouter
router-view
router-link
useRouter
useRoute
params
query
beforeEach
二百九十七、必须掌握 Axios
axios.create
baseURL
GET
POST
PUT
DELETE
params
Request Interceptor
Response Interceptor
二百九十八、必须掌握 Element Plus
Button
Input
Form
Table
Dialog
Select
Pagination
Message
MessageBox
二百九十九、必须掌握联调
Vite 5173
SpringBoot 8080
CORS
Proxy
Network
JSON
Token
401
403
三百、面试题 1
问:
Vue 是什么?
答:
Vue 是一个渐进式 JavaScript 前端框架。
它的核心思想包括
数据驱动视图和组件化开发。
Vue 3 中常使用 Composition API
和 Single File Component 组织应用。
三百零一、面试题 2
问:
ref 和 reactive 有什么区别?
答:
ref 可以包装任意值,
JavaScript 中读取和修改通常通过 .value。
reactive 主要用于对象类型,
可以直接通过对象属性读取和修改。
模板中 ref 通常会自动解包。
三百零二、面试题 3
问:
computed 和 watch 区别?
答:
computed 主要用于根据现有响应式数据
计算出新的派生值,并且具有缓存特性。
watch 用于监听数据变化后执行副作用,
例如重新请求接口或写入存储。
三百零三、面试题 4
问:
v-if 和 v-show 区别?
答:
v-if 会根据条件真正创建或销毁对应 DOM。
v-show 通常保留 DOM,
通过 CSS display 控制显示隐藏。
频繁切换可以考虑 v-show,
很少切换可以使用 v-if。
三百零四、面试题 5
问:
为什么 v-for 要使用 key?
答:
key 用来帮助 Vue 识别列表节点的稳定身份,
提高更新效率并避免错误复用组件状态。
通常应使用数据库 id 等稳定唯一值,
不建议在会增删排序的列表中使用 index。
三百零五、面试题 6
问:
Vue 父子组件如何通信?
答:
父组件向子组件传数据主要使用 Props。
子组件向父组件通知事件主要使用 Emit。
如果要传入一段 UI 内容,
可以使用 Slot。
三百零六、面试题 7
问:
Vue Router 是什么?
答:
Vue Router 是 Vue 单页应用的路由解决方案。
它可以根据浏览器 URL
在 router-view 中切换不同页面组件,
而不需要每次从服务器重新加载完整 HTML。
三百零七、面试题 8
问:
Axios 拦截器有什么作用?
答:
请求拦截器可以统一给请求增加 Token、
Header 等信息。
响应拦截器可以统一处理响应格式、
401、403 和错误提示。
这样可以避免每个 API 重复写相同代码。
三百零八、面试题 9
问:
为什么 Vue 前端访问 SpringBoot 会跨域?
答:
浏览器的 Origin 由协议、主机和端口组成。
开发环境中 Vue 通常运行在 5173,
SpringBoot 通常运行在 8080,
端口不同就属于不同源。
可以通过后端 CORS
或 Vite 开发代理解决。
三百零九、面试题 10
问:
为什么 Postman 成功但浏览器 CORS 失败?
答:
CORS 属于浏览器的同源安全机制。
Postman 不是浏览器页面,
通常不会受到浏览器同源策略的限制。
所以 Postman 接口成功,
不代表浏览器跨域配置一定正确。
三百一十、面试题 11
问:
前端隐藏按钮能不能代替后端权限?
答:
不能。
前端隐藏按钮只能改善用户体验。
用户仍然可以使用 Postman
或自己构造 HTTP 请求调用接口。
真正权限控制必须由后端完成。
三百一十一、面试题 12
问:
Vite 是做什么的?
答:
Vite 是现代前端开发和构建工具。
开发阶段提供 Dev Server 和快速热更新,
生产阶段通过 build 命令
生成优化后的静态资源。
三百一十二、面试题 13
问:
npm install 做了什么?
答:
npm 会根据 package.json
以及 lock 文件解析依赖,
把需要的包安装到 node_modules。
它在前端依赖管理中的角色
和 Maven 管理 Java 依赖有一定相似之处。
三百一十三、面试题 14
问:
Vue 页面怎么调用 SpringBoot?
答:
Vue 页面触发事件以后,
调用封装在 api 模块中的 Axios 方法。
Axios 发送 HTTP 请求到 SpringBoot Controller,
后端处理后返回 JSON。
前端把 JSON data 写入 ref/reactive,
Vue 再根据响应式数据自动更新页面。
三百一十四、面试题 15
问:
为什么前端不能保存真正的 Secret?
答:
Vue 最终会构建成发送给浏览器的 JavaScript 和静态资源。
用户可以查看这些客户端文件,
因此数据库密码、JWT 私钥、
云服务 SecretKey 等真正敏感密钥
必须保存在后端。
三百一十五、Vue 知识结构
Vue 3
│
├─ Project
│ ├─ Node
│ ├─ npm
│ ├─ create-vue
│ └─ Vite
│
├─ Core
│ ├─ ref
│ ├─ reactive
│ ├─ computed
│ ├─ watch
│ └─ lifecycle
│
├─ Template
│ ├─ interpolation
│ ├─ v-bind
│ ├─ v-on
│ ├─ v-model
│ ├─ v-if
│ └─ v-for
│
├─ Component
│ ├─ props
│ ├─ emit
│ └─ slot
│
├─ Router
│ ├─ path
│ ├─ params
│ ├─ query
│ └─ guard
│
├─ HTTP
│ ├─ Axios
│ ├─ Request Interceptor
│ ├─ Response Interceptor
│ └─ API Module
│
├─ UI
│ └─ Element Plus
│
└─ Backend
├─ SpringBoot
├─ RESTful
├─ JSON
├─ Token
├─ CORS
└─ Vite Proxy
三百一十六、Vue 和 Java 后端知识对应
Vue package.json
≈
Maven pom.xml
npm
≈
Maven 依赖管理工具
Vue Component
≈
可复用 UI 类/模块思想
Props
≈
方法参数的单向输入思想
Router
≈
前端 URL 路由
Axios
≈
HTTP Client
request.js
≈
统一 HTTP 工具封装
Vue DTO Object
↔
SpringBoot DTO
JSON
↔
@RequestBody / Response Body
三百一十七、完整前后端项目结构
前端:
vue-admin
│
├─ src
│ ├─ api
│ ├─ components
│ ├─ router
│ ├─ utils
│ ├─ views
│ ├─ App.vue
│ └─ main.js
└─ package.json
后端:
springboot-rbac
│
├─ controller
├─ service
├─ mapper
├─ entity
├─ dto
├─ vo
└─ application.yml
三百一十八、完整联调图
Vue UserView
↓
@click
↓
loadUsers
↓
user.js
↓
request.js
↓
Axios
↓
Vite Proxy
↓
SpringBoot 8080
↓
Auth Interceptor
↓
UserController
↓
UserService
↓
UserMapper
↓
MySQL
↓
Result<PageResult<UserVO>>
↓
JSON
↓
Axios Response Interceptor
↓
users.value
↓
Element Plus Table
三百一十九、AI 驱动完整开发流程
需求
↓
数据库设计
↓
SpringBoot API
↓
Postman 验证
↓
接口文档
↓
给 AI 明确 Vue 技术栈和接口
↓
生成 Vue 页面
↓
npm run dev
↓
F12 Network
↓
修复接口和字段
↓
组件拆分
↓
统一 request.js
↓
完善权限
↓
npm run build
三百二十、本章总结
这一章最重要的是从:
Java 后端思维
成功切换到:
前后端分离思维
Vue 负责:
页面
交互
组件
状态
路由
SpringBoot 负责:
业务
权限
数据库
安全
API
Vue 核心:
ref
reactive
computed
watch
v-model
v-if
v-for
component
组件通信:
Props
Emit
Slot
路由:
Vue Router
HTTP:
Axios
后台 UI:
Element Plus
前后端联调:
Vue 5173
↓
Vite Proxy
↓
SpringBoot 8080
权限:
前端菜单/按钮
只负责展示
后端
负责真正鉴权
最重要调试工具:
F12
↓
Console
+
Network
使用 AI 时必须记住:
AI 生成的是初稿
接口和项目约束必须明确告诉 AI
自己必须能运行、验证和修改
到这里,你应该已经能完成:
Vue3 项目创建
基础组件页面
Element Plus 表单和表格
Vue Router 页面跳转
Axios 调 SpringBoot
Token 自动携带
401 / 403 处理
学生/用户管理 CRUD 页面
第三阶段课程表里:
AI 驱动 Web - Vue
还有第二部分。
下一篇会继续深入:
Vue 企业项目进阶
+
Pinia
+
动态路由
+
权限菜单
+
组件封装
+
Axios 完整封装
+
Layout
+
Element Plus 后台框架
+
SpringBoot RBAC 前后端完整联调
官方工具链参考
Vue 官方新项目脚手架:
https://vuejs.org/guide/scaling-up/tooling
https://cn.vuejs.org/guide/quick-start
Vite:
https://vite.dev/guide/
Element Plus:
https://element-plus.org/zh-CN/guide/quickstart.html
说明:
前端工具链更新较快。
如果实际创建项目时出现 Node 版本、
依赖版本或脚手架提示差异,
以当时官方文档和命令行提示为准。