AI 前端开发培训手册

AI 前端开发培训手册

目标读者 :后端工程师
培训目标 :建立"后端思维 + AI 工具"的前端开发工作流,能独立用 AI 完成管理后台页面从 0 到对接真实接口的完整交付
核心理念:你不是要成为前端专家,而是要成为"能驾驭 AI 的前端开发者"


目录


第一章:培训目标与定位

1.1 培训结束后的四个能力

  1. 认知能力:理解为什么后端思维可以直接迁移到前端开发,建立正确的心智模型
  2. 核心知识:掌握 Vue 3 或 React 18 的"最小必要知识"------只学能帮你"看懂和修改 AI 代码"的那部分
  3. AI 工作流:熟练使用 Cursor + Claude 完成从需求描述到可运行页面的全流程
  4. 实战交付:能独立用 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 选型建议

  1. 公司现有项目用什么,你就选什么。因为有现成代码可以参考,有同事可以问。
  2. 如果自由选择,建议选 React。AI 生成代码质量更稳,长期职业选择面更广。
  3. 这不是终身大事。两门框架核心概念相通,学会一门,另一门一周就能上手。

第四章:最小必要前端知识

4.1 知识减负原则

不需要学 HTML 全标签、不需要手写复杂 CSS、不需要搞懂 Webpack 配置。你只需要掌握**"能看懂和修改 AI 代码"**的那部分。

4.2 四大知识块

HTML(只需知道这些)
  • 表单元素:inputselecttextareaform
  • 容器:div(块级)、span(行内)
  • 语义化标签:headermainsectionfooter
  • 属性:classiddata-*
CSS(理解概念即可,不用手写)
  • Flex 布局 :横向/纵向排列、居中对齐、间距分配

    css 复制代码
    .container {
      display: flex;
      justify-content: space-between; /* 两端对齐 */
      align-items: center;             /* 垂直居中 */
      gap: 16px;                       /* 子元素间距 */
    }
  • Grid 布局:二维网格(管理后台表格布局常用)

  • Box Model:content → padding → border → margin

  • 常用属性widthheightmarginpaddingcolorbackground-colorborder-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>

逐行解读

  1. loading:布尔值,控制表格 loading 动画。请求发送时 true,结束 false
  2. tableData:表格数据源。初始空数组,接口返回后填充。用 ref 是因为要替换整个数组引用。
  3. searchForm:搜索条件放在 reactive 对象里。重置时只需清空对象属性。
  4. fetchData:核心方法。和后端 Controller 写法几乎一样:async/awaittry/catch、接口调用。区别只是多了 loading.value 控制。
  5. 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 写一个用户管理列表页。

功能:

  1. 搜索:用户名输入框、状态下拉框、搜索按钮、重置按钮
  2. 表格:ID、用户名、邮箱、状态 Tag、创建时间、操作列
  3. 分页:支持页码和页大小切换
  4. 加载状态:请求时表格显示 loading
  5. 空状态:无数据时显示 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-htmldangerouslySetInnerHTML 渲染富文本,因为这是最简单的方案。

危险

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 堆栈 前端不知道该怎么提示用户

建议

  1. 分页参数统一page / pageSize / total
  2. 返回结构统一{ code, data, message }
  3. 枚举值友好:同时返回编码和中文
  4. 列表加统计:顺便返回 summary 统计信息
  5. 错误信息结构化:错误码 + 用户友好提示 + 可选详细说明

13.2 接口评审请前端参加

很多后端觉得"接口是我自己写的,不需要别人审",但前端能看出你意识不到的问题:字段命名不一致、缺少必要字段、返回数据量过大等。

13.3 文档同步

Swagger 文档必须和代码同步。前端按文档开发,联调时发现不一致会很崩溃。


第十四章:学习路径与成长路线图

14.1 四阶段成长路线

第一周:看懂代码
  • 跟着模板,独立完成 3 个页面
  • 不要复制粘贴,逐行理解每个 API 的作用
  • 开始积累自己的 Prompt 模板库
第二到四周:独立开发
  • 选一个真实需求,从接口设计到页面开发独立完成
  • 学会用浏览器 DevTools 调试:
    • Network 面板:看请求/响应、过滤接口
    • Console 面板:看报错、打印调试
    • Elements 面板:看 DOM 结构、临时改样式
第二到三个月:工程化
  • 封装可复用的组件和 Hooks
  • 配置代码规范(ESLint + Prettier)
  • 学习基础性能优化
持续精进
  • 关注前端技术动态
  • 参与团队 Code Review
  • 输出技术博客或内部分享

14.2 DevTools 速学

  1. Network:看接口请求状态、请求参数、响应数据
  2. Console:看 JS 报错、用 console.log 调试
  3. Elements:看 DOM 结构、临时改样式验证效果
  4. 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 使用建议

  1. 不要收藏夹吃灰:遇到问题直接打开对应文档查
  2. 优先官方文档:组件库的 API 文档是最权威的
  3. AI 辅助阅读:把英文文档链接丢给 AI,让它帮你总结
  4. 建立自己的知识库:用 Notion / 飞书 / 语雀 整理个人笔记和 Prompt

最后记住这个公式

复制代码
后端思维 + AI 工具 + 最小前端知识 = 独立交付前端页面

你不需要成为前端专家。你需要成为"能驾驭 AI 的前端开发者"。

三个行动项

  1. 本周内,用模板独立完成第一个页面
  2. 本月内,建立个人 Prompt 库(积累 10 个场景)
  3. 持续养成"生成 → 审查 → 调优"的习惯

AI 是副驾驶,你是机长。

相关推荐
新芒18 小时前
卡萨帝20年:中国高端制造转型的分水岭
人工智能·制造
郑寿昌18 小时前
华为发布韬定律:突破摩尔定律的新范式
人工智能
有一只柴犬18 小时前
从拼接走向统一:商汤SenseNova-U1如何重新定义多模态AI
人工智能
imbackneverdie18 小时前
AI生成PPT全流程攻略
人工智能·信息可视化·aigc·powerpoint·ppt·科研工具·ai生图
艺舟先生18 小时前
开源agent源码架构分析之claude(一)
人工智能·架构·开源
掘根18 小时前
【openCV】鼠标操作,像素类型转换与归一化
人工智能·opencv·计算机视觉
一个数据大开发18 小时前
AI 不止改变工作,也将重构生活:从效率工具到个人生活操作系统
大数据·人工智能·生活
肖有米XTKF864618 小时前
肖有米开发团队:推三返一模式系统开发-推三返一商业平台小程序介绍
人工智能·小程序·团队开发·csdn开发云
程序员三明治18 小时前
【AI】Tika:一次文档解析引擎的工程实践
java·人工智能·大模型·llm·后端开发·rag·tika文件解析
小新同学^O^18 小时前
简单学习 -->AI Skills
人工智能·学习·skill