Vue3+SpringBoot全栈开发:从零实现增删改查与分页功能

前言

在现代化Web应用开发中,前后端分离架构已成为主流。本文将详细介绍如何使用Vue3作为前端框架,SpringBoot作为后端框架,实现一套完整的增删改查(CRUD)功能,包含分页查询、条件筛选等企业级特性。

技术栈介绍

  • 前端:Vue3 + Element Plus + Axios

  • 后端:SpringBoot + MyBatis-Plus

  • 构建工具:Vite (前端) + Maven (后端)

一、环境准备与项目搭建

1.1 前端项目初始化

bash

复制

下载

复制代码
npm init vue@latest vue3-springboot-crud
cd vue3-springboot-crud
npm install axios element-plus --save

1.2 后端项目搭建

使用Spring Initializr创建项目,添加以下依赖:

  • Spring Web

  • MyBatis Framework

  • Lombok

  • MySQL Driver

二、核心功能实现

2.1 跨域解决方案

前后端分离开发首要解决跨域问题,SpringBoot后端配置如下:

java

复制

下载

复制代码
@Configuration
public class CrossConfig {
    private static final long MAX_AGE = 24 * 60 * 60;

    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        config.setMaxAge(MAX_AGE);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

2.2 前端Axios封装

javascript

复制

下载

复制代码
import axios from "axios";
import { ElMessage } from 'element-plus'

const http = axios.create({
    baseURL: import.meta.env.VITE_API_BASE_URL,
    timeout: 50000
})

// 请求拦截器
http.interceptors.request.use(config => {
    config.headers['Content-Type'] = "application/json;charset=utf-8"
    const user = JSON.parse(localStorage.getItem("user") || '{}')
    if (user.token) {
        config.headers['Authorization'] = `Bearer ${user.token}`
    }
    return config
})

// 响应拦截器
http.interceptors.response.use(response => {
    if (response.data.code !== 200) {
        ElMessage.error(response.data.message)
    }
    return response.data
}, error => {
    ElMessage.error(error.message)
    return Promise.reject(error)
})

export default http

三、分页查询实现

3.1 后端分页逻辑

java

复制

下载

复制代码
@PostMapping("/list_page")
public Result<PageResult<User>> listPage(@RequestBody PageQuery<User> query) {
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    if (StringUtils.isNotBlank(query.getEntity().getName())) {
        wrapper.like("name", query.getEntity().getName());
    }
    
    int total = userMapper.selectCount(wrapper);
    PageHelper.startPage(query.getCurrentPage(), query.getPageSize());
    List<User> list = userMapper.selectList(wrapper);
    
    return Result.success(new PageResult<>(total, list));
}

3.2 前端分页组件

vue

复制

下载

复制代码
<template>
  <div class="pagination-container">
    <el-pagination
      v-model:current-page="queryParams.currentPage"
      v-model:page-size="queryParams.pageSize"
      :page-sizes="[10, 20, 50, 100]"
      layout="total, sizes, prev, pager, next"
      :total="total"
      @size-change="handleQuery"
      @current-change="handleQuery"
    />
  </div>
</template>

<script setup>
import { reactive, ref } from 'vue'
import http from '@/utils/request'

const queryParams = reactive({
  currentPage: 1,
  pageSize: 10,
  name: ''
})

const total = ref(0)
const tableData = ref([])

const handleQuery = async () => {
  const res = await http.post('/user/list_page', queryParams)
  tableData.value = res.data.list
  total.value = res.data.total
}
</script>

四、完整CRUD实现

4.1 新增数据

java

复制

下载

复制代码
@PostMapping("/add")
public Result<String> addUser(@RequestBody User user) {
    user.setCreateTime(LocalDateTime.now());
    userMapper.insert(user);
    return Result.success("添加成功");
}

4.2 更新数据

java

复制

下载

复制代码
@PostMapping("/update")
public Result<String> updateUser(@RequestBody User user) {
    user.setUpdateTime(LocalDateTime.now());
    userMapper.updateById(user);
    return Result.success("更新成功");
}

4.3 删除数据

java

复制

下载

复制代码
@PostMapping("/delete")
public Result<String> deleteUser(@RequestBody List<Long> ids) {
    if (ids != null && !ids.isEmpty()) {
        userMapper.deleteBatchIds(ids);
    }
    return Result.success("删除成功");
}

五、前端界面优化

5.1 表格与表单组件

vue

复制

下载

复制代码
<template>
  <div class="app-container">
    <!-- 查询表单 -->
    <el-form :inline="true" class="search-form">
      <el-form-item label="用户名">
        <el-input v-model="queryParams.name" clearable @clear="handleQuery" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="handleQuery">查询</el-button>
        <el-button @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>
    
    <!-- 操作按钮 -->
    <div class="operation-buttons">
      <el-button type="primary" @click="handleAdd">新增</el-button>
      <el-button type="danger" @click="handleBatchDelete">批量删除</el-button>
    </div>
    
    <!-- 数据表格 -->
    <el-table
      v-loading="loading"
      :data="tableData"
      @selection-change="handleSelectionChange"
    >
      <el-table-column type="selection" width="55" />
      <el-table-column prop="name" label="姓名" />
      <el-table-column prop="age" label="年龄" />
      <el-table-column label="操作" width="200">
        <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>
    
    <!-- 分页组件 -->
    <pagination
      v-show="total > 0"
      :total="total"
      v-model:page="queryParams.currentPage"
      v-model:limit="queryParams.pageSize"
      @pagination="handleQuery"
    />
    
    <!-- 新增/编辑对话框 -->
    <el-dialog v-model="dialogVisible" :title="dialogTitle">
      <el-form :model="form" :rules="rules" ref="formRef">
        <el-form-item label="姓名" prop="name">
          <el-input v-model="form.name" />
        </el-form-item>
        <el-form-item label="年龄" prop="age">
          <el-input-number v-model="form.age" :min="0" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitForm">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

六、性能优化建议

  1. 后端优化

    • 使用MyBatis-Plus的分页插件替代手动分页

    • 添加Redis缓存高频访问数据

    • 对大数据量查询添加索引

  2. 前端优化

    • 使用防抖处理频繁查询

    • 添加表格加载状态

    • 实现数据懒加载

javascript

复制

下载

复制代码
// 防抖处理示例
import { debounce } from 'lodash-es'

const debouncedQuery = debounce(handleQuery, 500)

七、常见问题解决

  1. 跨域问题:确保后端正确配置CORS,前端请求地址正确

  2. 分页失效:检查分页参数是否正确传递,后端SQL是否正确拼接

  3. 数据更新不及时:在增删改操作后重新查询数据

  4. 批量操作失败:检查后端是否支持批量操作,参数格式是否正确

结语

本文详细介绍了基于Vue3和SpringBoot的全栈CRUD开发流程,涵盖了从基础查询到复杂分页的实现,以及前后端交互的最佳实践。读者可以根据实际需求扩展更多功能,如表单验证、文件上传、权限控制等。欢迎交流。

相关推荐
yuren_xia3 小时前
Spring Boot中保存前端上传的图片
前端·spring boot·后端
JohnYan6 小时前
Bun技术评估 - 04 HTTP Client
javascript·后端·bun
shangjg36 小时前
Kafka 的 ISR 机制深度解析:保障数据可靠性的核心防线
java·后端·kafka
青莳吖7 小时前
使用 SseEmitter 实现 Spring Boot 后端的流式传输和前端的数据接收
前端·spring boot·后端
我的golang之路果然有问题8 小时前
ElasticSearch+Gin+Gorm简单示例
大数据·开发语言·后端·elasticsearch·搜索引擎·golang·gin
穗余8 小时前
NodeJS全栈开发面试题讲解——P5前端能力(React/Vue + API调用)
javascript·vue.js·react.js
椰椰椰耶9 小时前
[网页五子棋][匹配模块]实现胜负判定,处理玩家掉线
java·开发语言·spring boot·websocket·spring
mldong9 小时前
我的全栈工程师之路:全栈学习路线分享
前端·后端
早知道不学Java了10 小时前
chromedriver 下载失败
前端·vue.js·react.js·npm·node.js
噼里啪啦啦.10 小时前
SpringBoot统一功能处理
java·spring boot·后端