Vue 全栈技术栈

    最后更新: 2025年11月26日

    技术栈概述

    Vue全栈 是捷码AI提供的前后端分离解决方案,后端使用Spring Boot提供RESTful API,前端使用Vue 3 + Element Plus构建现代化用户界面。

    技术组成

    层次技术版本说明
    前端Vue3.x渐进式JavaScript框架
    前端Element Plus2.xVue 3组件库
    前端Vite5.x构建工具
    前端Axios1.xHTTP客户端
    后端Spring Boot2.7/3.x后端框架
    后端MyBatis-Plus3.5.xORM框架

    核心特性

    • 前后端分离:独立开发、独立部署
    • 现代化UI:Element Plus美观组件
    • 响应式设计:适配多种屏幕
    • RESTful API:标准化接口设计

    Vue 全栈与微信小程序的关系

    系统提供两个平台枚举使用 Vue 全栈后端:

    平台代码平台名称前端技术后端共享适用场景
    VUEVue 全栈Vue 3 + Element PlusWeb 应用、管理后台
    VUE_WXAPP微信小程序微信小程序原生共享 Vue 后端移动端小程序

    💡 重要说明:微信小程序(VUE_WXAPP)继承了 Vue 全栈的后端实现(WxAppMerger extends VueMerger),共享相同的 Spring Boot RESTful API,仅前端使用微信小程序原生技术。

    选择建议

    • 需要 Web 应用或管理后台 → 选择 VUE
    • 需要微信小程序 → 选择 VUE_WXAPP(自动生成小程序前端 + Spring Boot 后端)
    • 需要 Web + 小程序双端 → 分别生成两个项目,共享后端 API

    项目结构

    整体结构

    ProjectName/ ├── backend/ # 后端项目 │ ├── src/main/java/ │ ├── src/main/resources/ │ └── pom.xml ├── frontend/ # 前端项目 │ ├── src/ │ │ ├── api/ # API接口 │ │ ├── assets/ # 静态资源 │ │ ├── components/ # 公共组件 │ │ ├── router/ # 路由配置 │ │ ├── store/ # 状态管理 │ │ ├── views/ # 页面组件 │ │ ├── App.vue │ │ └── main.js │ ├── index.html │ ├── vite.config.js │ └── package.json └── sql/ └── schema.sql

    前端详细结构

    frontend/src/ ├── api/ # API接口封装 │ ├── request.js # Axios封装 │ └── student.js # 学生模块API ├── assets/ # 静态资源 │ ├── images/ │ └── styles/ │ └── index.css ├── components/ # 公共组件 │ ├── Pagination.vue # 分页组件 │ └── SearchForm.vue # 搜索表单 ├── router/ # 路由配置 │ └── index.js ├── store/ # Pinia状态管理 │ └── index.js ├── views/ # 页面组件 │ ├── student/ │ │ ├── List.vue # 列表页 │ │ └── Edit.vue # 编辑页 │ └── Home.vue ├── App.vue # 根组件 └── main.js # 入口文件

    后端代码

    Controller (RESTful API)

    @RestController @RequestMapping("/api/student") @CrossOrigin(origins = "*") public class StudentController { @Autowired private StudentService studentService; @GetMapping("/list") public ApiResult<IPage<Student>> list( @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer size, @RequestParam(required = false) String keyword) { Page<Student> pageParam = new Page<>(page, size); IPage<Student> result = studentService.pageByKeyword(pageParam, keyword); return ApiResult.success(result); } @GetMapping("/{id}") public ApiResult<Student> getById(@PathVariable Long id) { return ApiResult.success(studentService.getById(id)); } @PostMapping public ApiResult<Boolean> save(@RequestBody Student student) { return ApiResult.success(studentService.save(student)); } @PutMapping public ApiResult<Boolean> update(@RequestBody Student student) { return ApiResult.success(studentService.updateById(student)); } @DeleteMapping("/{id}") public ApiResult<Boolean> delete(@PathVariable Long id) { return ApiResult.success(studentService.removeById(id)); } }

    统一响应格式

    @Data public class ApiResult<T> { private Integer code; private String message; private T data; public static <T> ApiResult<T> success(T data) { ApiResult<T> result = new ApiResult<>(); result.setCode(200); result.setMessage("success"); result.setData(data); return result; } public static <T> ApiResult<T> error(Integer code, String message) { ApiResult<T> result = new ApiResult<>(); result.setCode(code); result.setMessage(message); return result; } }

    前端代码

    main.js

    import { createApp } from 'vue' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import zhCn from 'element-plus/dist/locale/zh-cn.mjs' import App from './App.vue' import router from './router' const app = createApp(App) app.use(ElementPlus, { locale: zhCn }) app.use(router) app.mount('#app')

    Axios封装 (api/request.js)

    import axios from 'axios' import { ElMessage } from 'element-plus' const request = axios.create({ baseURL: '/api', timeout: 10000 }) // 请求拦截器 request.interceptors.request.use( config => { const token = localStorage.getItem('token') if (token) { config.headers['Authorization'] = 'Bearer ' + token } return config }, error => Promise.reject(error) ) // 响应拦截器 request.interceptors.response.use( response => { const res = response.data if (res.code !== 200) { ElMessage.error(res.message || '请求失败') return Promise.reject(new Error(res.message)) } return res.data }, error => { ElMessage.error(error.message || '网络错误') return Promise.reject(error) } ) export default request

    API模块 (api/student.js)

    import request from './request' export function getStudentList(params) { return request({ url: '/student/list', method: 'get', params }) } export function getStudentById(id) { return request({ url: `/student/${id}`, method: 'get' }) } export function saveStudent(data) { return request({ url: '/student', method: 'post', data }) } export function updateStudent(data) { return request({ url: '/student', method: 'put', data }) } export function deleteStudent(id) { return request({ url: `/student/${id}`, method: 'delete' }) }

    列表页 (views/student/List.vue)

    <template> <div class="student-list"> <el-card> <!-- 搜索区域 --> <el-form :inline="true" :model="queryParams"> <el-form-item label="关键字"> <el-input v-model="queryParams.keyword" placeholder="请输入姓名或学号" /> </el-form-item> <el-form-item> <el-button type="primary" @click="handleSearch">搜索</el-button> <el-button @click="handleReset">重置</el-button> <el-button type="success" @click="handleAdd">新增</el-button> </el-form-item> </el-form> <!-- 表格 --> <el-table :data="tableData" stripe border> <el-table-column prop="id" label="ID" width="80" /> <el-table-column prop="name" label="姓名" /> <el-table-column prop="studentNo" label="学号" /> <el-table-column prop="gender" label="性别" width="80"> <template #default="scope"> {{ scope.row.gender === 1 ? '男' : '女' }} </template> </el-table-column> <el-table-column label="操作" width="180"> <template #default="scope"> <el-button size="small" @click="handleEdit(scope.row)">编辑</el-button> <el-button size="small" type="danger" @click="handleDelete(scope.row)">删除</el-button> </template> </el-table-column> </el-table> <!-- 分页 --> <el-pagination v-model:current-page="queryParams.page" v-model:page-size="queryParams.size" :total="total" layout="total, sizes, prev, pager, next" @current-change="fetchData" @size-change="fetchData" /> </el-card> </div> </template> <script setup> import { ref, onMounted } from 'vue' import { useRouter } from 'vue-router' import { ElMessage, ElMessageBox } from 'element-plus' import { getStudentList, deleteStudent } from '@/api/student' const router = useRouter() const tableData = ref([]) const total = ref(0) const queryParams = ref({ page: 1, size: 10, keyword: '' }) const fetchData = async () => { const res = await getStudentList(queryParams.value) tableData.value = res.records total.value = res.total } const handleSearch = () => { queryParams.value.page = 1 fetchData() } const handleReset = () => { queryParams.value = { page: 1, size: 10, keyword: '' } fetchData() } const handleAdd = () => { router.push('/student/add') } const handleEdit = (row) => { router.push(`/student/edit/${row.id}`) } const handleDelete = async (row) => { await ElMessageBox.confirm('确定删除该学生吗?', '提示') await deleteStudent(row.id) ElMessage.success('删除成功') fetchData() } onMounted(() => { fetchData() }) </script> <style scoped> .student-list { padding: 20px; } </style>

    配置说明

    后端CORS配置

    @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("*") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("*"); } }

    前端代理配置 (vite.config.js)

    export default defineConfig({ server: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } } })

    启动说明

    启动后端

    cd backend mvn spring-boot:run

    启动前端

    cd frontend npm install npm run dev

    访问地址


    数据库支持

    支持的数据库类型

    数据库版本驱动类
    MySQL5.7+com.mysql.cj.jdbc.Driver
    SQLite3.xorg.sqlite.JDBC
    SQL Server2012+com.microsoft.sqlserver.jdbc.SQLServerDriver

    ⚠️ 注意:系统当前仅支持以上 3 种数据库。如需其他数据库(如 PostgreSQL、Oracle),需要手动修改配置和驱动。


    常见问题

    Q1: VUE 和 VUE_WXAPP 有什么区别?

    主要区别

    • VUE:生成 Vue 3 Web 前端 + Spring Boot 后端
    • VUE_WXAPP:生成微信小程序前端 + Spring Boot 后端(共享 Vue 的后端实现)

    后端完全相同,区别仅在前端技术栈。

    Q2: 可以同时生成 Web 和小程序吗?

    可以!分别使用 VUEVUE_WXAPP 生成两个项目:

    1. 使用 VUE 生成 Web 端项目
    2. 使用 VUE_WXAPP 生成小程序端项目
    3. 两个项目的后端 API 完全兼容,可以共享数据库

    Q3: 前后端如何联调?

    开发阶段

    1. 前端使用 Vite 代理(vite.config.js 配置 proxy)
    2. 后端运行在 http://localhost:8080
    3. 前端运行在 http://localhost:5173

    生产部署

    • 前端打包后部署到 Nginx
    • 后端部署到服务器
    • Nginx 配置反向代理到后端 API

    Q4: Element Plus 组件找不到?

    确保已正确安装依赖:

    cd frontend npm install element-plus

    Q5: 为什么选择 Vue 全栈?

    Vue 全栈的优势

    • ✅ 现代化的用户体验(Vue 3 + Element Plus)
    • ✅ 前后端分离,便于团队协作
    • ✅ RESTful API 设计,易于扩展
    • ✅ 适合中大型项目和企业应用

    如果需要移动端,建议选择 VUE_WXAPP(微信小程序)。


    💡 提示:Vue全栈是最现代化的技术栈选择,适合需要优秀用户体验的项目。前后端分离也便于团队协作开发。

    本文对您有帮助吗?
    提交反馈