AI 前端开发培训手册
目标读者 :后端工程师
培训目标 :建立"后端思维 + AI 工具"的前端开发工作流,能独立用 AI 完成管理后台页面从 0 到对接真实接口的完整交付
核心理念:你不是要成为前端专家,而是要成为"能驾驭 AI 的前端开发者"
目录
- 第一章:培训目标与定位
- [第二章:为什么后端工程师特别适合学 AI 前端](#第二章:为什么后端工程师特别适合学 AI 前端)
- 第三章:技术栈选型
- 第四章:最小必要前端知识
- [第五章:Vue 3 核心概念](#第五章:Vue 3 核心概念)
- [第六章:React 18 核心概念](#第六章:React 18 核心概念)
- [第七章:AI 工具全景与选型](#第七章:AI 工具全景与选型)
- [第八章:Cursor 实战工作流](#第八章:Cursor 实战工作流)
- [第九章:Prompt 工程](#第九章:Prompt 工程)
- 第十章:标准开发工作流
- 第十一章:安全意识
- 第十二章:避坑指南
- 第十三章:前后端协作最佳实践
- 第十四章:学习路径与成长路线图
- [附录 A:Prompt 模板库](#附录 A:Prompt 模板库)
- [附录 B:Vue vs React 概念对照表](#附录 B:Vue vs React 概念对照表)
- [附录 C:推荐资源清单](#附录 C:推荐资源清单)
第一章:培训目标与定位
1.1 培训结束后的四个能力
- 认知能力:理解为什么后端思维可以直接迁移到前端开发,建立正确的心智模型
- 核心知识:掌握 Vue 3 或 React 18 的"最小必要知识"------只学能帮你"看懂和修改 AI 代码"的那部分
- AI 工作流:熟练使用 Cursor + Claude 完成从需求描述到可运行页面的全流程
- 实战交付:能独立用 AI 完成一个管理后台页面,从 0 到对接真实接口跑通
1.2 后端工程师的先天优势
| 后端能力 | 如何迁移到前端 |
|---|---|
| 理解业务和数据流 | 前端本质是"数据 + 状态 = 界面",业务逻辑是一样的 |
| 熟悉 API 设计 | 前端工作就是"消费 API",Swagger 文档就是最好的 Prompt |
| 掌握编程基础 | JavaScript 90% 的语法和后端语言相同 |
| 工程化思维 | 前端同样需要模块化、状态管理、错误处理 |
| 安全意识 | XSS/CSRF 防护、输入校验等安全知识是相通的 |
AI 正在抹平的差距 :CSS 属性记不住?没关系。你描述"一个蓝色圆角按钮,hover 时变深一点",AI 直接生成。你需要成为的是需求描述专家,而不是 CSS 专家。
第二章:为什么后端工程师特别适合学 AI 前端
2.1 一个真实场景
假设你刚写完用户管理的后端接口:分页查询、条件筛选、批量删除。接口测试通过了,Swagger 文档也更新了。但你现在想看一下页面长什么样------
以前的做法 :
提需求 → 等排期 → 等开发 → 等联调。整个过程可能要一周。
培训后的做法 :
把 Swagger 文档丢给 AI,10 分钟生成页面骨架,30 分钟对接真实接口,一小时以内你就能在浏览器里看到完整页面。
这就是自给自足的能力。
2.2 AI 时代的前端开发范式转移
| 传统前端开发 | AI 辅助前端开发 |
|---|---|
| 记住大量 API 和属性 | 描述需求,让 AI 生成 |
| 手写 CSS 调像素 | 描述视觉效果,让 AI 生成 |
| 背诵框架文档 | 理解核心概念,让 AI 补细节 |
| weeks 才能上手项目 | hours 就能产出可用页面 |
核心公式:
后端思维 + AI 工具 + 最小前端知识 = 独立交付前端页面
第三章:技术栈选型
3.1 Vue 3 vs React 18:六维对比
| 维度 | Vue 3 | React 18 | 后端工程师视角 |
|---|---|---|---|
| 上手门槛 | 模板语法接近 HTML,直觉性强 | JSX 本质就是 JS,灵活但初期会晕 | Vue 更像"模板引擎",React 更像"函数编程" |
| AI 代码质量 | 生态相对小,AI 训练数据少 | 生态更大,GitHub 项目更多,AI 输出更稳 | React 胜出,同样 Prompt 生成的代码 bug 更少 |
| 管理后台生态 | Element Plus、Ant Design Vue | Ant Design 5、Arco Design | 两者都非常成熟 |
| 类型支持 | 对 TypeScript 支持良好 | 原生拥抱 TypeScript | React 的类型推断更精准 |
| 招聘/职业 | 中小厂、外包项目多 | 大厂、外企占有率更高 | React 长期选择面更广 |
| 心智模型 | 数据驱动视图,自动更新 | 状态变化 → 函数重执行 → 新视图 | Vue 像"观察者模式",React 像"纯函数" |
3.2 选型建议
- 公司现有项目用什么,你就选什么。因为有现成代码可以参考,有同事可以问。
- 如果自由选择,建议选 React。AI 生成代码质量更稳,长期职业选择面更广。
- 这不是终身大事。两门框架核心概念相通,学会一门,另一门一周就能上手。
第四章:最小必要前端知识
4.1 知识减负原则
不需要学 HTML 全标签、不需要手写复杂 CSS、不需要搞懂 Webpack 配置。你只需要掌握**"能看懂和修改 AI 代码"**的那部分。
4.2 四大知识块
HTML(只需知道这些)
- 表单元素:
input、select、textarea、form - 容器:
div(块级)、span(行内) - 语义化标签:
header、main、section、footer - 属性:
class、id、data-*
CSS(理解概念即可,不用手写)
-
Flex 布局 :横向/纵向排列、居中对齐、间距分配
css.container { display: flex; justify-content: space-between; /* 两端对齐 */ align-items: center; /* 垂直居中 */ gap: 16px; /* 子元素间距 */ } -
Grid 布局:二维网格(管理后台表格布局常用)
-
Box Model:content → padding → border → margin
-
常用属性 :
width、height、margin、padding、color、background-color、border-radius
JavaScript(你已会 90%)
前端 JS 和后端 JS 语法几乎一样。只需补充:
document.querySelector------ 获取 DOM 元素addEventListener------ 绑定事件fetch/axios------ HTTP 请求JSON.parse/JSON.stringify------ 数据序列化
注意:在现代框架(Vue/React)中,你很少直接操作 DOM。
TypeScript(强烈推荐使用)
类型定义就是最好的 Prompt。你给 AI 一个 interface,它就知道接口返回什么字段、什么类型,生成的代码准确率大幅提升。
typescript
// 给 AI 这个接口定义,它生成的代码会直接使用这些类型
interface User {
id: number;
name: string;
email: string;
status: 'active' | 'inactive';
createdAt: string;
}
interface ApiResponse<T> {
code: number;
data: T;
message: string;
}
4.3 学习路径速览
每天 30 分钟,一周达到"看懂 AI 代码"的水平:
| 天数 | 内容 | 目标 |
|---|---|---|
| Day 1 | HTML + CSS 基础概念 | 能看懂标签和简单样式 |
| Day 2 | JS 前端特有 API | 能看懂 DOM 操作和事件 |
| Day 3 | TypeScript 基础 | 能写简单的 interface |
| Day 4 | 框架核心概念(Vue 或 React) | 能看懂组件结构 |
| Day 5 | 组件库使用 | 能在官方文档查 API |
| Day 6 | AI 工具上手 | 能用 Cursor 生成简单页面 |
| Day 7 | 综合实战 | 独立完成一个列表页 |
第五章:Vue 3 核心概念
5.1 为什么先讲 Vue
Vue 的语法对后端工程师更友好。模板语法接近 HTML,v-if 就像写 if 语句,v-for 就像写 for 循环。
5.2 五个核心概念(掌握这五个,80% 的页面都能看懂)
1. ref ------ 管理基础类型状态
vue
<script setup>
import { ref } from 'vue'
// ref 返回一个对象,通过 .value 访问和修改
const count = ref(0)
const loading = ref(false)
const keyword = ref('')
// 修改时必须用 .value
count.value++
loading.value = true
</script>
<template>
<!-- 模板中自动解包,不需要 .value -->
<p>{{ count }}</p>
<button @click="count++">+1</button>
</template>
后端类比 :有点像
AtomicInteger,不能直接改 int,要通过方法改。
2. reactive ------ 管理对象类型状态
vue
<script setup>
import { reactive } from 'vue'
// reactive 的对象可以直接修改属性,不需要 .value
const form = reactive({
keyword: '',
status: '',
dateRange: []
})
// 直接修改属性
form.keyword = '张三'
form.status = 'active'
</script>
建议 :表单统一用
reactive,因为表单天然就是对象结构。
3. computed ------ 派生状态(自动缓存)
vue
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('张')
const lastName = ref('三')
// 自动缓存,只有依赖变化时才重新计算
const fullName = computed(() => {
return firstName.value + lastName.value
})
</script>
后端类比:就像数据库视图或计算字段。
4. watch ------ 监听器
vue
<script setup>
import { ref, watch } from 'vue'
const searchKeyword = ref('')
// 当 searchKeyword 变化时,自动执行回调
watch(searchKeyword, (newVal, oldVal) => {
console.log('搜索词从', oldVal, '变成', newVal)
fetchData() // 自动触发搜索
})
// 监听对象深层属性,需要加 { deep: true }
watch(form, () => { ... }, { deep: true })
</script>
后端类比:数据库触发器或消息队列消费者。
5. 生命周期钩子
| 钩子 | 后端类比 | 用途 |
|---|---|---|
onMounted |
构造函数 | 页面加载完成,发起初始请求 |
onUnmounted |
析构函数 | 页面销毁,清理定时器/WebSocket |
onUpdated |
- | 数据更新后操作 DOM |
vue
<script setup>
import { onMounted, onUnmounted } from 'vue'
let timer = null
onMounted(() => {
fetchData() // 页面加载完自动请求数据
timer = setInterval(() => { ... }, 5000) // 开启定时器
})
onUnmounted(() => {
clearInterval(timer) // 必须清理,否则内存泄漏
})
</script>
5.3 一个完整的 Vue 列表页
vue
<template>
<div>
<!-- 搜索表单 -->
<el-form :model="searchForm" inline>
<el-form-item label="关键词">
<el-input v-model="searchForm.keyword" placeholder="请输入用户名" />
</el-form-item>
<el-form-item label="状态">
<el-select v-model="searchForm.status">
<el-option label="全部" value="" />
<el-option label="启用" value="active" />
<el-option label="禁用" value="inactive" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">搜索</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
<!-- 数据表格 -->
<el-table :data="tableData" v-loading="loading">
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="name" label="用户名" />
<el-table-column prop="email" label="邮箱" />
<el-table-column prop="status" label="状态">
<template #default="{ row }">
<el-tag :type="row.status === 'active' ? 'success' : 'danger'">
{{ row.status === 'active' ? '启用' : '禁用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createdAt" label="创建时间" />
<el-table-column label="操作" width="150">
<template #default="{ row }">
<el-button type="primary" size="small" @click="handleEdit(row)">编辑</el-button>
<el-button type="danger" size="small" @click="handleDelete(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
v-model:current-page="pagination.page"
v-model:page-size="pagination.pageSize"
:total="pagination.total"
@change="handlePageChange"
/>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import axios from 'axios'
// ========== 状态定义 ==========
const loading = ref(false)
const tableData = ref([])
const searchForm = reactive({
keyword: '',
status: ''
})
const pagination = reactive({
page: 1,
pageSize: 10,
total: 0
})
// ========== 方法定义 ==========
const fetchData = async () => {
loading.value = true
try {
const { data } = await axios.get('/api/users', {
params: {
page: pagination.page,
pageSize: pagination.pageSize,
...searchForm
}
})
tableData.value = data.list
pagination.total = data.total
} finally {
loading.value = false
}
}
const handleSearch = () => {
pagination.page = 1
fetchData()
}
const handleReset = () => {
searchForm.keyword = ''
searchForm.status = ''
handleSearch()
}
const handlePageChange = () => {
fetchData()
}
const handleEdit = (row) => {
// 跳转编辑页或打开弹窗
console.log('编辑', row)
}
const handleDelete = async (row) => {
await axios.delete(`/api/users/${row.id}`)
fetchData() // 刷新列表
}
// ========== 生命周期 ==========
onMounted(() => {
fetchData()
})
</script>
逐行解读:
loading:布尔值,控制表格 loading 动画。请求发送时true,结束false。tableData:表格数据源。初始空数组,接口返回后填充。用ref是因为要替换整个数组引用。searchForm:搜索条件放在reactive对象里。重置时只需清空对象属性。fetchData:核心方法。和后端 Controller 写法几乎一样:async/await、try/catch、接口调用。区别只是多了loading.value控制。onMounted:页面加载后自动发起请求。对应后端"服务启动后自动执行初始化任务"。
核心洞察:Vue 页面的逻辑和后端 Controller 层几乎一样------定义状态变量 → 定义业务方法 → 在合适的时机调用。模板部分只是数据的"呈现层"。
5.4 Vue 工程化三件套
Pinia ------ 状态管理(类似后端的 Service 层)
typescript
// stores/user.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useUserStore = defineStore('user', () => {
// State
const token = ref(localStorage.getItem('token') || '')
const userInfo = ref(null)
// Getter(类似 computed)
const isLoggedIn = computed(() => !!token.value)
// Action(类似方法)
const setToken = (newToken: string) => {
token.value = newToken
localStorage.setItem('token', newToken)
}
const logout = () => {
token.value = ''
userInfo.value = null
localStorage.removeItem('token')
}
return { token, userInfo, isLoggedIn, setToken, logout }
})
Vue Router ------ 路由管理
typescript
// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
component: () => import('../views/Layout.vue'),
children: [
{ path: 'users', component: () => import('../views/UserList.vue') },
{ path: 'departments', component: () => import('../views/DeptList.vue') }
]
},
{ path: '/login', component: () => import('../views/Login.vue') }
]
})
// 路由守卫(类似后端拦截器)
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
if (to.path !== '/login' && !token) {
next('/login')
} else {
next()
}
})
export default router
Axios 封装 ------ HTTP 请求
typescript
// utils/request.ts
import axios from 'axios'
import { useUserStore } from '@/stores/user'
import router from '@/router'
const request = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000
})
// 请求拦截器:自动加 Token
request.interceptors.request.use((config) => {
const token = useUserStore().token
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
// 响应拦截器:统一错误处理
request.interceptors.response.use(
(response) => response.data,
(error) => {
if (error.response?.status === 401) {
useUserStore().logout()
router.push('/login')
}
return Promise.reject(error)
}
)
export default request
第六章:React 18 核心概念
6.1 React 的心智模型
Vue 的思维:数据是响应式的,你改了数据,Vue 自动帮你更新界面。
React 的思维:数据变化 → 整个函数重新执行一遍 → 生成新的界面。
这是两套完全不同的哲学。Vue 像"自动档",React 像"手动档"。
6.2 五个核心 Hooks
1. useState ------ 状态管理
tsx
import { useState } from 'react'
function Counter() {
// 返回数组 [state, setState]
const [count, setCount] = useState(0)
const [loading, setLoading] = useState(false)
// 状态不可变!不能直接修改,必须通过 setState
const increment = () => {
setCount(count + 1) // ✅ 正确
// count++ // ❌ 错误!直接修改不会触发更新
}
return (
<div>
<p>{count}</p>
<button onClick={increment}>+1</button>
</div>
)
}
核心规则:state 是不可变的。这就像后端的事务------状态变更必须通过正式的 API。
2. useEffect ------ 副作用处理
tsx
import { useState, useEffect } from 'react'
import axios from 'axios'
function UserList() {
const [users, setUsers] = useState([])
// 第二个参数是依赖数组
useEffect(() => {
// 组件挂载时执行
fetchUsers()
// 返回清理函数(组件卸载时执行)
return () => {
// 清理定时器、取消请求等
}
}, []) // 空数组 = 只在挂载时执行一次
const fetchUsers = async () => {
const { data } = await axios.get('/api/users')
setUsers(data)
}
return <div>{/* ... */}</div>
}
依赖数组规则:
[]------ 只在挂载时执行(= Vue 的onMounted)[userId]------ 挂载时 + userId 变化时执行- 不写 ------ 每次渲染都执行(通常要避免)
3. useCallback ------ 缓存函数引用
tsx
import { useState, useCallback } from 'react'
function Parent() {
const [count, setCount] = useState(0)
// 用 useCallback 缓存函数,避免每次渲染都创建新函数
const handleClick = useCallback(() => {
console.log('clicked')
}, []) // 空依赖 = 永远不重新创建
return (
<div>
<button onClick={() => setCount(c => c + 1)}>+1</button>
<Child onClick={handleClick} />
</div>
)
}
何时使用:当函数作为 props 传给子组件时,为了避免不必要的子组件重渲染。
4. useMemo ------ 缓存计算结果
tsx
import { useState, useMemo } from 'react'
function UserList({ users }) {
const [filter, setFilter] = useState('')
// 缓存过滤结果,只有 users 或 filter 变化时才重新计算
const filteredUsers = useMemo(() => {
return users.filter(u => u.name.includes(filter))
}, [users, filter])
return <div>{/* 使用 filteredUsers */}</div>
}
5. useRef ------ 引用(不触发渲染)
tsx
import { useRef, useEffect } from 'react'
function Timer() {
const timerRef = useRef(null)
const countRef = useRef(0) // 修改不会触发重渲染
useEffect(() => {
timerRef.current = setInterval(() => {
countRef.current++
console.log(countRef.current)
}, 1000)
return () => clearInterval(timerRef.current)
}, [])
return <div>看控制台</div>
}
6.3 一个完整的 React 列表页
tsx
import { useState, useEffect, useCallback } from 'react'
import { Table, Form, Input, Select, Button, Pagination, Tag, message } from 'antd'
import axios from 'axios'
interface User {
id: number
name: string
email: string
status: 'active' | 'inactive'
createdAt: string
}
interface PaginationData {
page: number
pageSize: number
total: number
}
function UserList() {
// ========== 状态定义 ==========
const [loading, setLoading] = useState(false)
const [tableData, setTableData] = useState<User[]>([])
const [pagination, setPagination] = useState<PaginationData>({
page: 1,
pageSize: 10,
total: 0
})
const [form] = Form.useForm()
// ========== 方法定义 ==========
const fetchData = useCallback(async () => {
setLoading(true)
try {
const values = form.getFieldsValue()
const { data } = await axios.get('/api/users', {
params: {
page: pagination.page,
pageSize: pagination.pageSize,
...values
}
})
setTableData(data.list)
setPagination(prev => ({ ...prev, total: data.total }))
} finally {
setLoading(false)
}
}, [pagination.page, pagination.pageSize, form])
// ========== 副作用 ==========
useEffect(() => {
fetchData()
}, [fetchData])
// ========== 事件处理 ==========
const handleSearch = () => {
setPagination(prev => ({ ...prev, page: 1 }))
fetchData()
}
const handleReset = () => {
form.resetFields()
handleSearch()
}
const handleDelete = async (record: User) => {
await axios.delete(`/api/users/${record.id}`)
message.success('删除成功')
fetchData()
}
// ========== 表格列定义 ==========
const columns = [
{ title: 'ID', dataIndex: 'id', width: 80 },
{ title: '用户名', dataIndex: 'name' },
{ title: '邮箱', dataIndex: 'email' },
{
title: '状态',
dataIndex: 'status',
render: (status: string) => (
<Tag color={status === 'active' ? 'success' : 'error'}>
{status === 'active' ? '启用' : '禁用'}
</Tag>
)
},
{ title: '创建时间', dataIndex: 'createdAt' },
{
title: '操作',
render: (_: any, record: User) => (
<>
<Button type="link" onClick={() => console.log('编辑', record)}>编辑</Button>
<Button type="link" danger onClick={() => handleDelete(record)}>删除</Button>
</>
)
}
]
// ========== JSX 渲染 ==========
return (
<div>
<Form form={form} layout="inline" onFinish={handleSearch}>
<Form.Item name="keyword" label="关键词">
<Input placeholder="请输入用户名" />
</Form.Item>
<Form.Item name="status" label="状态">
<Select placeholder="请选择" allowClear>
<Select.Option value="active">启用</Select.Option>
<Select.Option value="inactive">禁用</Select.Option>
</Select>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">搜索</Button>
<Button onClick={handleReset}>重置</Button>
</Form.Item>
</Form>
<Table
dataSource={tableData}
columns={columns}
loading={loading}
rowKey="id"
pagination={false}
/>
<Pagination
current={pagination.page}
pageSize={pagination.pageSize}
total={pagination.total}
onChange={(page, pageSize) => {
setPagination({ page, pageSize, total: pagination.total })
}}
/>
</div>
)
}
export default UserList
核心差异对比 Vue:
| 特性 | Vue | React |
|---|---|---|
| 状态读取 | count.value(ref)/ obj.prop(reactive) |
直接读变量 |
| 状态修改 | .value = newVal / 直接改属性 |
必须通过 setXxx |
| 计算属性 | computed() |
useMemo() |
| 监听 | watch() |
useEffect() |
| 模板 | <template> 标签 |
JSX(函数返回值) |
| 生命周期 | onMounted / onUnmounted |
useEffect(() => { ... return () => {} }, []) |
6.4 React 工程化三件套
Zustand ------ 极简状态管理
typescript
// stores/userStore.ts
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
interface UserState {
token: string
userInfo: any
isLoggedIn: boolean
setToken: (token: string) => void
logout: () => void
}
export const useUserStore = create<UserState>()(
persist(
(set) => ({
token: '',
userInfo: null,
isLoggedIn: false,
setToken: (token) => set({ token, isLoggedIn: !!token }),
logout: () => set({ token: '', userInfo: null, isLoggedIn: false })
}),
{ name: 'user-storage', partialize: (state) => ({ token: state.token }) }
)
)
Zustand 的优势 :可以在组件外部访问
useUserStore.getState().token,这在 Axios 拦截器里非常有用。
React Router 6
tsx
// router/index.tsx
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
const router = createBrowserRouter([
{
path: '/',
element: <Layout />,
children: [
{ path: 'users', element: <UserList /> },
{ path: 'departments', element: <DeptList /> }
]
},
{ path: '/login', element: <Login /> }
])
// main.tsx
<RouterProvider router={router} />
Axios 封装(React 版)
typescript
// utils/request.ts
import axios from 'axios'
import { useUserStore } from '@/stores/userStore'
const request = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000
})
request.interceptors.request.use((config) => {
// Zustand 可以在组件外访问
const token = useUserStore.getState().token
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
request.interceptors.response.use(
(response) => response.data,
(error) => {
if (error.response?.status === 401) {
useUserStore.getState().logout()
window.location.href = '/login'
}
return Promise.reject(error)
}
)
export default request
第七章:AI 工具全景与选型
7.1 工具分类
| 类型 | 工具 | 用途 | 推荐场景 |
|---|---|---|---|
| AI IDE | Cursor、Windsurf、Trae | 代码生成/重构主力 | 日常开发 |
| 大模型 | Claude 3.7 Sonnet、GPT-4o | 复杂逻辑、跨文件重构 | 复杂任务 |
| 原型工具 | v0.dev、Bolt.new、Lovable | 快速生成页面原型 | 出 Demo |
| 代码补全 | GitHub Copilot、Codeium | 行级/块级补全 | 辅助编码 |
7.2 推荐组合
- 日常开发:Cursor(主)+ Claude(复杂任务)
- 快速原型:v0.dev / Bolt.new
- 预算有限:Trae / Codeium + ChatGPT 免费版
7.3 为什么推荐 Cursor
Cursor 是 AI 原生 IDE------整个编辑器围绕 AI 设计,不是传统 IDE 加插件:
- Ctrl+K:选中代码后直接说"改成 XXX"
- Ctrl+L:打开 AI 对话面板,支持 Chat 和 Agent 两种模式
- @ 符号:引用项目里的其他文件,AI 能读懂你的项目结构
- 代码补全:不是一行一行补,可以一次性生成整个函数
第八章:Cursor 实战工作流
8.1 标准操作流程
场景:用 AI 生成一个用户管理列表页
步骤 1:创建项目
bash
npm create vite@latest vue-admin -- --template vue-ts
cd vue-admin
npm install element-plus axios vue-router pinia
npm run dev
步骤 2:创建页面文件
新建 src/views/UserList.vue
步骤 3:写 Prompt(按 Ctrl+L 打开 AI 面板)
请帮我写一个 Vue 3.4 + TypeScript + Element Plus 的用户管理列表页。
技术栈:
- Vue 3.4 Composition API + <script setup>
- TypeScript(严格模式,不要用 any)
- Element Plus 组件库
- Axios 请求封装在 @/utils/request
功能需求:
1. 搜索区域:用户名输入框、状态下拉框、搜索按钮、重置按钮
2. 表格展示:ID、用户名、邮箱、状态(用 Tag 组件)、创建时间、操作列(编辑/删除按钮)
3. 分页功能
4. 页面加载时自动请求数据
5. 删除操作需要二次确认
接口定义:
GET /api/users
参数:{ page: number, pageSize: number, keyword?: string, status?: string }
返回:{ code: number, data: { list: User[], total: number }, message: string }
User 类型:
interface User {
id: number
name: string
email: string
status: 'active' | 'inactive'
createdAt: string
}
输出要求:
- 使用 ref 和 reactive 管理状态
- 使用 Element Plus 的 el-table、el-pagination、el-form 等组件
- 表格需要 loading 状态
- 空数据时显示 "暂无数据"
- 代码注释用中文
步骤 4:审查 AI 代码
AI 生成后,重点检查:
- 技术栈版本是否正确(Vue 3 不是 Vue 2)
- 组件名是否正确(
el-table不是el-data-table) - 是否处理了 loading、error、empty 三种状态
- 是否有内存泄漏(定时器/WebSocket 是否清理)
步骤 5:Apply 并运行
点击 Apply 应用代码 → npm run dev → 浏览器查看效果
步骤 6:对接真实接口
将 mock 数据替换为真实的 request.get('/api/users') 调用
8.2 Agent 模式 vs Chat 模式
| 模式 | 用途 | 特点 |
|---|---|---|
| Chat | 问答、代码生成 | AI 生成代码,你手动 Apply |
| Agent | 复杂任务、多文件操作 | AI 自动创建文件、执行终端命令 |
复杂需求(涉及 3 个以上文件)用 Agent 模式;简单需求用 Chat 模式。
第九章:Prompt 工程
9.1 黄金 Prompt 结构
【技术栈声明】精确到 minor 版本
【功能需求】用编号列表,一条一个功能
【接口定义】数据结构越详细越好
【输出要求】语法、TS 严格度、注释语言、是否需要测试
9.2 垃圾 Prompt vs 黄金 Prompt
垃圾 Prompt:
帮我写一个用户管理页面,要好看一点,功能全一点。
问题:技术栈不确定、没有接口定义、"好看"无法量化、"全"太模糊。
黄金 Prompt:
请用 Vue 3.4 + TypeScript + Element Plus 2.5 写一个用户管理列表页。
功能:
- 搜索:用户名输入框、状态下拉框、搜索按钮、重置按钮
- 表格:ID、用户名、邮箱、状态 Tag、创建时间、操作列
- 分页:支持页码和页大小切换
- 加载状态:请求时表格显示 loading
- 空状态:无数据时显示 Empty 组件
接口:GET /api/users,参数 { page, pageSize, keyword, status }
返回 { code, data: { list: User[], total }, message }
要求:严格 TypeScript,不用 any,代码注释中文。
9.3 六大场景 Prompt 模板
场景 1:列表页生成
请用 [技术栈] 写一个 [模块名] 管理列表页。
功能:
1. 搜索条件:[具体字段]
2. 表格字段:[字段列表]
3. 分页功能
4. 批量操作:[删除/导出/审核]
5. 操作列:[编辑/删除/详情]
接口:
GET [接口地址]
参数:[参数定义]
返回:[返回结构]
输出要求:
- 处理 loading、error、empty 三种状态
- 使用 [组件库] 组件
- 严格 TypeScript
场景 2:表单页生成
请用 [技术栈] 写一个 [模块名] [新增/编辑] 表单页。
表单字段:
1. [字段名]:[类型],[是否必填],[校验规则]
2. ...
接口:
POST [接口地址](新增)
PUT [接口地址]/:id(编辑)
GET [接口地址]/:id(详情回显)
输出要求:
- 表单校验规则完整
- 提交按钮 loading 状态
- 提交成功返回上一页
- 严格 TypeScript
场景 3:对接真实接口
请把以下 mock 数据代码改成对接真实接口。
当前代码:
[粘贴代码]
接口信息:
- 地址:[地址]
- 方法:[GET/POST/PUT/DELETE]
- 参数:[参数]
- 返回:[返回结构]
要求:
- 使用已有的 request 封装
- 处理 loading、error、empty 状态
- 接口报错时给用户友好提示
场景 4:代码审查
请审查以下代码,找出潜在问题:
[粘贴代码]
关注:
1. 安全问题(XSS、CSRF)
2. 性能问题(重复渲染、大数据处理)
3. 边界情况(空数据、超长文本)
4. 内存泄漏(定时器、订阅未清理)
5. TypeScript 类型是否准确
场景 5:框架迁移(Vue ↔ React)
请将以下 Vue 组件转成 React 组件:
[粘贴 Vue 代码]
要求:
- 使用 React 18 Hooks
- 使用 [Ant Design / 其他组件库]
- 保持原有功能不变
- 严格 TypeScript
场景 6:调试排错
我的代码出现以下问题:
问题描述:[具体现象]
错误信息:[粘贴报错]
相关代码:
[粘贴代码]
请帮我定位原因并给出修复方案。
第十章:标准开发工作流
10.1 五步工作流
写 Prompt → AI 生成初版 → 对接真实接口 → 审查与调优 → 交付与复盘
第一步:写 Prompt(10 分钟)
Prompt 的质量直接决定输出代码的质量。花 10 分钟写一个好的 Prompt,能省下一小时的调试时间。
检查清单:
- 技术栈和版本号明确
- 功能需求用编号列表
- 接口数据结构完整
- 输出要求具体
第二步:AI 生成初版
- 用 Cursor Chat 模式做第一轮生成
- 复杂需求用 Agent 模式,让 AI 自动创建多个文件
第三步:对接真实接口
AI 最容易出错的环节。注意:
- 把 mock 数据替换为真实请求
- 处理三种状态:loading (加载中)、success (有数据)、empty(无数据)
- 检查请求参数和响应结构是否匹配
第四步:审查与调优
安全检查:
- 是否有 XSS 风险?(是否用了
v-html/dangerouslySetInnerHTML) - 敏感操作是否有二次确认?
性能检查:
- 大数据列表是否分页?
- 是否做了不必要的重渲染?
边界检查:
- 空数组会不会报错?
- 超长文本会不会撑破布局?
- 接口报错时页面会不会白屏?
第五步:交付与复盘
- 跑一遍主流程
- 让前端同事做 Code Review
- 把这个场景的 Prompt 整理成模板,下次直接用
10.2 核心铁律
AI 是副驾驶,你是机长。
AI 可以帮你开飞机,但起飞、降落、遇到气流时的决策,必须是你来做。
如果你看不懂 AI 生成的代码,就不要合并到项目里。
第十一章:安全意识
11.1 AI 生成代码的三大安全隐患
1. XSS(跨站脚本攻击)
AI 特别喜欢用 v-html 或 dangerouslySetInnerHTML 渲染富文本,因为这是最简单的方案。
危险:
vue
<!-- ❌ 危险:如果 content 包含用户输入 -->
<div v-html="content"></div>
解法:
vue
<!-- ✅ 安全:优先用纯文本渲染 -->
<div>{{ content }}</div>
<!-- ✅ 如果必须用富文本,先用 DOMPurify 消毒 -->
<div v-html="purify(content)"></div>
2. CSRF(跨站请求伪造)
- Axios 拦截器统一加上
Authorization头 - 敏感操作(删除、转账)必须加二次确认
- Cookie 设置
SameSite属性
3. 输入校验缺失
AI 生成的表单代码通常只做了前端校验。
重要 :前端校验是用户体验 ,后端校验是安全底线。AI 没写后端校验,你自己补上。
第十二章:避坑指南
12.1 六大陷阱
| 陷阱 | 现象 | 解法 |
|---|---|---|
| AI 幻觉组件 | 编译报错,组件不存在 | 对照官方文档核对组件名和 API |
| 样式灾难 | 大量内联样式,无法复用 | 强制使用 UI 框架组件,禁止手写复杂 CSS |
| 状态不同步 | 修改数据页面不更新 | Vue 通过官方 API 修改;React 通过 setState |
| 边界遗漏 | 无 loading、无空状态、报错白屏 | 强制三态检查:loading / success / empty |
| 内存泄漏 | 定时器/WebSocket 未清理 | Vue 在 onUnmounted 清理;React 在 useEffect return 清理 |
| 过度渲染 | 列表卡顿、无限循环 | Vue v-for 加 key;React 检查 useEffect 依赖数组 |
12.2 常见错误速查
Vue 常见错误:
| 错误 | 原因 | 解法 |
|---|---|---|
| 修改数组页面不更新 | 直接通过索引修改 | 用 splice 或赋值新数组 |
| reactive 解构丢失响应式 | 解构会破坏代理 | 用 toRefs 或改用 ref |
| watch 监听不到深层变化 | 默认只监听引用 | 加 { deep: true } |
| onMounted 执行两次 | 开发环境严格模式 | 生产环境正常,忽略即可 |
React 常见错误:
| 错误 | 原因 | 解法 |
|---|---|---|
| useEffect 无限循环 | 依赖数组写错 | 用 useCallback 缓存函数 |
| 闭包陷阱 | 事件回调读取旧 state | 用函数式更新 setState(prev => ...) |
| Context 性能问题 | 小更新导致大量重渲染 | 拆分 Context,或用 Zustand |
| key 使用索引 | 列表项状态错乱 | 用数据唯一 ID 作为 key |
第十三章:前后端协作最佳实践
13.1 当你能写前端后,后端接口设计会变得更好
前端最讨厌的接口:
| 问题 | 例子 |
|---|---|
| 分页参数不统一 | 有的叫 pageNo,有的叫 pageNum |
| 返回结构不一致 | 有时候数组,有时候对象 |
| 枚举值只返回数字 | 前端要维护映射表 |
| 错误返回 Java 堆栈 | 前端不知道该怎么提示用户 |
建议:
- 分页参数统一 :
page/pageSize/total - 返回结构统一 :
{ code, data, message } - 枚举值友好:同时返回编码和中文
- 列表加统计:顺便返回 summary 统计信息
- 错误信息结构化:错误码 + 用户友好提示 + 可选详细说明
13.2 接口评审请前端参加
很多后端觉得"接口是我自己写的,不需要别人审",但前端能看出你意识不到的问题:字段命名不一致、缺少必要字段、返回数据量过大等。
13.3 文档同步
Swagger 文档必须和代码同步。前端按文档开发,联调时发现不一致会很崩溃。
第十四章:学习路径与成长路线图
14.1 四阶段成长路线
第一周:看懂代码
- 跟着模板,独立完成 3 个页面
- 不要复制粘贴,逐行理解每个 API 的作用
- 开始积累自己的 Prompt 模板库
第二到四周:独立开发
- 选一个真实需求,从接口设计到页面开发独立完成
- 学会用浏览器 DevTools 调试:
- Network 面板:看请求/响应、过滤接口
- Console 面板:看报错、打印调试
- Elements 面板:看 DOM 结构、临时改样式
第二到三个月:工程化
- 封装可复用的组件和 Hooks
- 配置代码规范(ESLint + Prettier)
- 学习基础性能优化
持续精进
- 关注前端技术动态
- 参与团队 Code Review
- 输出技术博客或内部分享
14.2 DevTools 速学
- Network:看接口请求状态、请求参数、响应数据
- Console:看 JS 报错、用 console.log 调试
- Elements:看 DOM 结构、临时改样式验证效果
- Application:看 LocalStorage、Cookie、SessionStorage
附录 A:Prompt 模板库
A.1 页面生成模板
markdown
## 列表页模板
请用 {技术栈} 写一个 {模块名} 管理列表页。
**技术栈**:{Vue 3.4 + TS + Element Plus / React 18 + TS + Ant Design 5}
**功能需求**:
1. 搜索区域:{字段列表}
2. 表格展示:{字段列表}
3. 分页功能
4. 操作列:{编辑/删除/详情}
5. 批量操作:{删除/导出}
**接口定义**:
- 列表接口:{GET /api/xxx}
- 参数:{page, pageSize, ...}
- 返回:{code, data: {list, total}, message}
**TypeScript 类型**:
```typescript
interface XXX {
// 字段定义
}
输出要求:
-
严格 TypeScript,禁止 any
-
处理 loading、error、empty 状态
-
代码注释中文
A.2 通用任务模板
markdown## 接口对接模板 请把以下代码中的 mock 数据改成对接真实接口。 当前代码:
粘贴代码
接口信息:
- 地址:{地址}
- 方法:{GET/POST/PUT/DELETE}
- 参数:{参数定义}
- 返回:{返回结构}
要求:
- 使用已有的 request 封装
- 处理 loading、error、empty 状态
- 接口报错时给用户友好提示
A.3 调试模板
markdown
## 问题排查模板
我的代码出现以下问题:
**问题描述**:{具体现象}
**错误信息**:
粘贴报错
**相关代码**:
粘贴代码
**环境信息**:
- 框架版本:{版本号}
- 浏览器:{浏览器及版本}
- 已尝试:{已尝试的解法}
请帮我定位原因并给出修复方案。
附录 B:Vue vs React 概念对照表
| 概念 | Vue 3 | React 18 |
|---|---|---|
| 状态管理(基础类型) | ref() + .value |
useState() + setter |
| 状态管理(对象类型) | reactive() |
useState() + 展开运算符 |
| 计算属性 | computed() |
useMemo() |
| 监听器 | watch() |
useEffect() |
| 函数缓存 | 不需要(自动) | useCallback() |
| 模板语法 | <template> + 指令 |
JSX(函数返回值) |
| 条件渲染 | v-if / v-show |
{condition && <Component />} |
| 列表渲染 | v-for + :key |
.map() + key |
| 挂载时执行 | onMounted() |
useEffect(() => {}, []) |
| 卸载时清理 | onUnmounted() |
useEffect(() => { return () => {} }, []) |
| 状态管理库 | Pinia | Zustand / Redux |
| 路由 | Vue Router 4 | React Router 6 |
| 表单处理 | v-model |
受控组件 + onChange |
| 样式作用域 | <style scoped> |
CSS Modules / Styled Components |
附录 C:推荐资源清单
C.1 官方文档(遇到具体问题再查)
| 资源 | 链接 | 说明 |
|---|---|---|
| Vue 3 官方文档 | https://cn.vuejs.org/ | 从"快速上手"开始看 |
| React 18 官方文档 | https://zh-hans.react.dev/ | Hooks 章节重点看 |
| TypeScript 官方文档 | https://www.typescriptlang.org/zh/docs/ | interface / generic 重点看 |
| MDN Web 文档 | https://developer.mozilla.org/zh-CN/ | HTML/CSS/JS 权威参考 |
C.2 UI 组件库
| 资源 | 技术栈 | 说明 |
|---|---|---|
| Element Plus | Vue 3 | 管理后台首选 |
| Ant Design 5 | React 18 | 国内最成熟的 React 组件库 |
| Ant Design Vue | Vue 3 | 阿里出品,企业级 |
| Arco Design | React/Vue | 字节跳动出品 |
C.3 AI 开发工具
| 工具 | 用途 | 费用 |
|---|---|---|
| Cursor | AI 原生 IDE,主力工具 | 免费版可用 |
| Claude 3.7 Sonnet | 代码理解和生成最强 | 免费版有限额 |
| v0.dev | React 页面 AI 生成 | 限量免费 |
| Bolt.new | 浏览器内全栈开发 | 限量免费 |
| Trae | 字节出品 AI IDE | 免费 |
C.4 代码模板与脚手架
| 工具 | 说明 |
|---|---|
| Vite | 下一代前端构建工具,启动秒开 |
| VueUse | Vue 常用 Hooks 集合 |
| React Use | React 常用 Hooks 集合 |
C.5 CSS 与样式
| 资源 | 说明 |
|---|---|
| Tailwind CSS | 原子化 CSS,AI 生成代码常用 |
| Flexbox 小游戏 | 30 分钟学会 Flex 布局 |
| Grid 花园 | 互动式学习 Grid 布局 |
C.6 使用建议
- 不要收藏夹吃灰:遇到问题直接打开对应文档查
- 优先官方文档:组件库的 API 文档是最权威的
- AI 辅助阅读:把英文文档链接丢给 AI,让它帮你总结
- 建立自己的知识库:用 Notion / 飞书 / 语雀 整理个人笔记和 Prompt
最后记住这个公式:
后端思维 + AI 工具 + 最小前端知识 = 独立交付前端页面你不需要成为前端专家。你需要成为"能驾驭 AI 的前端开发者"。
三个行动项:
- 本周内,用模板独立完成第一个页面
- 本月内,建立个人 Prompt 库(积累 10 个场景)
- 持续养成"生成 → 审查 → 调优"的习惯
AI 是副驾驶,你是机长。