Vue 全栈技术栈
最后更新: 2025年11月26日
技术栈概述
Vue全栈 是捷码AI提供的前后端分离解决方案,后端使用Spring Boot提供RESTful API,前端使用Vue 3 + Element Plus构建现代化用户界面。
技术组成
| 层次 | 技术 | 版本 | 说明 |
|---|---|---|---|
| 前端 | Vue | 3.x | 渐进式JavaScript框架 |
| 前端 | Element Plus | 2.x | Vue 3组件库 |
| 前端 | Vite | 5.x | 构建工具 |
| 前端 | Axios | 1.x | HTTP客户端 |
| 后端 | Spring Boot | 2.7/3.x | 后端框架 |
| 后端 | MyBatis-Plus | 3.5.x | ORM框架 |
核心特性
- ✅ 前后端分离:独立开发、独立部署
- ✅ 现代化UI:Element Plus美观组件
- ✅ 响应式设计:适配多种屏幕
- ✅ RESTful API:标准化接口设计
Vue 全栈与微信小程序的关系
系统提供两个平台枚举使用 Vue 全栈后端:
| 平台代码 | 平台名称 | 前端技术 | 后端共享 | 适用场景 |
|---|---|---|---|---|
| VUE | Vue 全栈 | Vue 3 + Element Plus | ✅ | Web 应用、管理后台 |
| 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
访问地址
数据库支持
支持的数据库类型
| 数据库 | 版本 | 驱动类 |
|---|---|---|
| MySQL | 5.7+ | com.mysql.cj.jdbc.Driver |
| SQLite | 3.x | org.sqlite.JDBC |
| SQL Server | 2012+ | 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 和小程序吗?
可以!分别使用 VUE 和 VUE_WXAPP 生成两个项目:
- 使用 VUE 生成 Web 端项目
- 使用 VUE_WXAPP 生成小程序端项目
- 两个项目的后端 API 完全兼容,可以共享数据库
Q3: 前后端如何联调?
开发阶段:
- 前端使用 Vite 代理(vite.config.js 配置 proxy)
- 后端运行在 http://localhost:8080
- 前端运行在 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全栈是最现代化的技术栈选择,适合需要优秀用户体验的项目。前后端分离也便于团队协作开发。
本文对您有帮助吗?
提交反馈