目錄
一、從0快速搭建SpringBoot3工程、SpringBoot3集成MyBatis、PageHelper分頁查詢的詳細教程。(博客鏈接)
二、實現前端與后端通信對接數據。(axios工具)
(1)安裝axios。(vue工程目錄)
(2)封裝請求工具類。(request.js)
<1>src目錄、utils目錄下。
<2>request.js代碼。(request攔截器、response攔截器)
<3>簡單請求示例。
前端請求后端接口代碼示例。
瀏覽器攔截非同源請求。(跨域請求問題)
<4>SpringBoot后端中配置統一跨域處理。
三、SpringBoot3+Vue3實現基本增刪改查。
(1)查詢。
<1>新建Employee.vue(員工信息頁面)。
<2>配置Employee.vue路由。
<3>頁面初級渲染效果。
<4>分頁查詢。("/employee/selectPage")
屬性:show-overflow-tooltip。
ElementUI的Pagination分頁事件(@size-change、@current-change)。
<5>條件查詢。
后端接口使用Employee對象接收參數。
EmployeeMapper。(動態SQL條件查詢)
<6>重置(reset)操作。
(2)新增。(Dialog對話框)
<1>新增對話框(彈窗)組件代碼示例。
<2>新增按鈕添加事件。
<3>對話框新增點擊保存,調用save方法。("/employee/add")
<4>后端代碼示例。
新增時頁面渲染效果。
(3)更新(編輯)。(表格操作欄的“編輯”)
<1>替換操作欄“編輯”、“刪除”樣式。(鏈接文字按鈕:link)
<2>“編輯”操作綁定事件handleUpdate(scope.row)函數。
行對象(scope.row)的淺拷貝問題。(錯誤!)
行對象的深拷貝。(JSON.stringify()、JSON.parse())
<3>區分新增操作的"保存"與編輯操作的"保存"。(post與put請求)
(4)刪除。(表格操作欄的“刪除”)
<1>單個刪除。
“刪除”的二次確認操作。(ElMessageBox.confirm())
<2>批量刪除。(type="selection")
使用@selection-change="xxx函數"。(獲取所選行對象)
使用map函數提取返回的數組中所選中行對象的id。
批量刪除的后端接口代碼。(controller)
service層。(依次調用deleteById)
前端代碼示例。
一、從0快速搭建SpringBoot3工程、SpringBoot3集成MyBatis、PageHelper分頁查詢的詳細教程。(博客鏈接)
- SpringBoot3實戰(從0快速搭建SpringBoot3工程、全局異常處理器、自定義封裝結果類、自定義異常)(2025詳細教程)(1)-CSDN博客
- SpringBoot3實戰(SpringBoot3集成MyBatis。PageHelper分頁查詢。get(查)、post(增)、put(改)、delete(刪)請求)(2)-CSDN博客
- 本篇博客的學習:實現SpringBoot3后端接口與Vue3前端頁面的連接互通。
- 之前的《SpringBoot3集成MyBatis》學習是使用Postman工具完成接口的調用與測試。
- 所以需要實現前端頁面數據的“分頁查詢”、“條件查詢”、“模糊查詢”、“新增”、“修改”、“刪除”、“批量刪除”等功能。
二、實現前端與后端通信對接數據。(axios工具)
(1)安裝axios。(vue工程目錄)
- 打開IDEA中的對應工程的終端。執行安裝axios命令。
cd .\自己vue工程對應目錄\npm i axios -S
(2)封裝請求工具類。(request.js)
- 實現前端向后端發起請求之前,需要使用一個封裝好的工具類。通過request.js幫助發起請求。功能:添加統一的請求頭、對后端服務器返回的數據進行統一處理等。
<1>src目錄、utils目錄下。
- 新建request.js文件。
<2>request.js代碼。(request攔截器、response攔截器)
import { ElMessage } from 'element-plus' import axios from "axios";const request = axios.create({//設置后臺請求地址baseURL: 'http://localhost:9090',timeout: 30000 // 后臺接口超時時間設置 })// request 攔截器(數據請求) // 可以自請求發送前對請求做一些處理 request.interceptors.request.use(config => {//設置統一的數據傳輸格式json、數據傳輸編碼utf-8config.headers['Content-Type'] = 'application/json;charset=utf-8';return config }, error => {return Promise.reject(error) });// response 攔截器 // 可以在接口響應后統一處理結果 request.interceptors.response.use(response => {//響應對象response中提取實際數據部分,存儲在變量res中let res = response.data;// 兼容服務端返回的字符串數據//如果res是字符串且不為空字符串,則使用JSON.parse方法將其解析為JavaScript對象;//如果 res 為空字符串,則保持原樣。if (typeof res === 'string') {res = res ? JSON.parse(res) : res}return res;},error => {if(error.response.status === 404){//404 狀態碼表示請求的資源未找到,通常意味著請求的接口不存在ElMessage.error('未找到請求接口')}else if(error.response.status === 500){//500:之前后端設置的全局系統異常處理捕獲//500 狀態碼表示服務器內部錯誤,通常是由于后端代碼出現異常ElMessage.error('系統異常,請查看后端控制臺報錯')}else{//其它情況統一打印錯誤信息console.error(error.message)}//將錯誤繼續拋出,以便后續的代碼可以繼續處理該錯誤return Promise.reject(error)} )export default request
<3>簡單請求示例。
- Manager.vue頁面的嵌套子頁面Home.vue進行簡單請求演示操作。
- 在<script>標簽下導入request.js中的request對象進行請求。
前端請求后端接口代碼示例。
<script setup>import {reactive} from "vue"; import request from "@/utils/request.js";//定義數據的常用方式 const data = reactive({employeeList:[], })request.get("employee/selectAll").then(res=>{alert(res)data.employeeList = res.data })</script>
瀏覽器攔截非同源請求。(跨域請求問題)
- 報錯原因:由于CORS(跨域資源共享)策略。請求被阻止,被請求的資源上不存在xxx頭 。
- 前端代碼在http://localhost:5173,而請求后端接口地址http://localhost:9090/xxx/xxx。二者源不同,瀏覽器的同源策略限制了這種跨域請求。需要在后端配置允許跨域的規則。
<4>SpringBoot后端中配置統一跨域處理。
- 在后端中新建一個類。跨越處理代碼示例如下。
- 配置完畢后,記得重啟后端工程。
package com.hyl.common;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.CorsFilter;/*** 跨域配置類。用于解決前端和后端由于不同源(協議、域名、端口不同)導致的跨域請求問題* @Configuration 讓該配置類注入到Spring容器中并能夠掃描到其下類下注解*/ @Configuration public class CorsConfig {/*** 創建并注冊CorsFilter bean,用于處理跨域請求* @return CorsFilter實例,Spring會在請求處理過程中使用該過濾器處理跨域請求* @Bean 注解會讓該方法的返回值注入到Spring容器中*/@Beanpublic CorsFilter corsFilter() {// 創建一個基于URL的跨域配置源對象,用于存儲和管理不同URL路徑的跨域配置UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();// 創建一個跨域配置對象,用于設置具體的跨域規則CorsConfiguration corsConfiguration = new CorsConfiguration();// 設置允許訪問的源地址,這里使用通配符"*",表示允許所有源地址訪問corsConfiguration.addAllowedOrigin("*");// 設置允許的請求頭,"*"表示允許所有請求頭,即前端可以在請求中攜帶任意請求頭corsConfiguration.addAllowedHeader("*");// 設置允許的請求方法,"*"表示允許所有的HTTP請求方法,如GET、POST、PUT、DELETE等corsConfiguration.addAllowedMethod("*");// 將跨域配置應用到所有的接口路徑上,"/**"表示匹配所有路徑source.registerCorsConfiguration("/**", corsConfiguration);// 創建并返回CorsFilter實例,傳入配置源對象,Spring會使用該過濾器處理跨域請求return new CorsFilter(source);} }
- 重新訪問http://localhost:5173/manager/home。查看請求結果。
- 發現:從后端訪問接口拿到數據庫數據并轉化成Java對象再以JSON格式返回給前端的數據無法通過彈窗在頁面顯示。
- 將alert()方法改為控制臺打印console.log()方法。
request.get("employee/selectAll").then(res=>{/*alert(res)*/console.log(res)data.employeeList = res.data })
三、SpringBoot3+Vue3實現基本增刪改查。
(1)查詢。
<1>新建Employee.vue(員工信息頁面)。
<template><div><div class="card" style="margin-bottom: 5px"><el-input style="width: 240px" v-model="data.name" placeholder="請根據名稱查詢" :prefix-icon="Search"></el-input><el-button type="primary" style="margin-left: 10px">查 詢</el-button><el-button type="warning" style="margin-left: 10px">重 置</el-button></div><div class="card" style="margin-bottom: 5px"><el-button type="primary" style="margin-left: 10px">新 增</el-button><el-button type="warning" style="margin-left: 10px">批量刪除</el-button><el-button type="info" style="margin-left: 10px">導 入</el-button><el-button type="success" style="margin-left: 10px">導 出</el-button></div><div class="card" style="margin-bottom: 5px"><div style="margin: 30px"><el-table :data="data.EmployeeList" stripe style="width: 100%"><el-table-column label="姓名" prop="name"/><el-table-column label="性別" prop="sex"/><el-table-column label="工號" prop="no"/><el-table-column label="年齡" prop="age"/><el-table-column label="個人簡介" prop="description"/><el-table-column label="部門" prop="departmentName"/><el-table-column label="操作"><template #default="scope"><el-button type="primary" circle><el-icon><Edit /></el-icon></el-button><el-button type="danger" circle><el-icon><Delete /></el-icon></el-button></template></el-table-column></el-table></div><div style="margin-top: 10px"><el-paginationv-model:current-page="data.pageNum"v-model:page-size="data.pageSize":page-sizes="[5, 10, 15, 20]"layout="total, sizes, prev, pager, next, jumper":total="data.total"/></div></div></div> </template><script setup>import {Delete, Edit, Search} from "@element-plus/icons-vue"; import {reactive} from "vue";const data = reactive({name:'',pageNum:1,pageSize:10,total:0,EmployeeList:[],})</script>
<2>配置Employee.vue路由。
import { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path:'/',redirect:'/manager/home'},{path:'/manager',meta:{ title:'父級頁面'},component: () => import('../views/Manager.vue'),children:[{path: 'home', name: 'home', meta:{ title:'主頁'}, component: () => import('../views/Home.vue')}, // url:/manager/home{path: 'test', name: 'test', meta:{ title:'測試數據頁01'}, component: () => import('../views/Test.vue')}, // url:/manager/test{path: 'demo', name: 'demo', meta:{ title:'測試數據頁02'}, component: () => import('../views/Demo.vue')}, // url:/manager/demo{path: 'data', name: 'data', meta:{ title:'數據展示頁面'}, component: () => import('../views/Data.vue')}, // url:/manager/data{path: 'employee', name: 'employee', meta:{ title:'員工信息頁面'}, component: () => import('../views/Employee.vue')}, // url:/manager/employee]},{path: '/404', name: 'NotFound', meta:{ title:'404找不到頁面'}, component: () => import('../views/404.vue')},{path:'/:pathMatch(.*)',redirect:'/404'}], })router.beforeEach((to,from,next)=>{//設置即將跳轉的路由頁面的網頁標題document.title=to.meta.titlenext() //必須調用的方法 })export default router
<3>頁面初級渲染效果。
<4>分頁查詢。("/employee/selectPage")
- 自定義load()函數發起后端接口("/employee/selectPage")的分頁請求。
- 后端代碼。(selectPage、selectAll)
/*** 查詢所有員工* 查詢使用get請求*/@GetMapping("/selectAll")public Result selectAll(){List<Employee> emList = employeeService.selectAll();return Result.success(emList);}/*** 分頁查詢* @param pageNum 當前頁碼。默認值1* @param pageSize 每頁數據個數。默認值10* @return*/@GetMapping("/selectPage")public Result selectPage(@RequestParam(defaultValue = "1") Integer pageNum,@RequestParam(defaultValue = "10") Integer pageSize){PageInfo<Employee> employeePageInfo = employeeService.selectPage(pageNum, pageSize);return Result.success(employeePageInfo);}
public List<Employee> selectAll() {return employeeMapper.selectAll();}/***service層實現分頁操作的代碼。PageHelper分頁插件使用。*/public PageInfo<Employee> selectPage(Integer pageNum,Integer pageSize) {//開啟分頁查詢(傳參:當前頁碼、每頁分頁個數)PageHelper.startPage(pageNum,pageSize);//查詢所有的數據List<Employee> employeeList = employeeMapper.selectAll();//PageInfo執行分頁操作return PageInfo.of(employeeList);}
- load()函數基礎代碼示例。
- 查看請求的控制臺信息。
- 完善后的load()函數代碼示例。
const load = () =>{//給后端發起request請求request.get("employee/selectPage",{ //參數示例:pageNum=xxx&pageSize=xxxparams:{pageNum:data.pageNum,pageSize:data.pageSize}}).then(res=>{/*console.log(res.data)*/data.EmployeeList = res.data.listdata.total = res.data.total}) }load()
屬性:show-overflow-tooltip。
- Element-UI的表格屬性:允許內容在一行內顯示,并在內容溢出時用省略號表示。同時當鼠標懸停時會顯示所有完整內容。
- Employee.vue的代碼示例。
<template><div><div class="card" style="margin-bottom: 5px"><el-input style="width: 240px" v-model="data.name" placeholder="請根據名稱查詢" :prefix-icon="Search"></el-input><el-button type="primary" style="margin-left: 10px" @click="load">查 詢</el-button> <!--v-for事件綁定可以用"@"代替--><el-button type="warning" style="margin-left: 10px">重 置</el-button></div><div class="card" style="margin-bottom: 5px"><el-button type="primary" style="margin-left: 10px">新 增</el-button><el-button type="warning" style="margin-left: 10px">批量刪除</el-button><el-button type="info" style="margin-left: 10px">導 入</el-button><el-button type="success" style="margin-left: 10px">導 出</el-button></div><div class="card" style="margin-bottom: 5px"><div style="margin: 30px"><el-table :data="data.EmployeeList" stripe style="width: 100%"><el-table-column label="姓名" prop="name"/><el-table-column label="性別" prop="sex"/><el-table-column label="工號" prop="no"/><el-table-column label="年齡" prop="age"/><el-table-column label="個人簡介" prop="description" show-overflow-tooltip/><el-table-column label="部門" prop="departmentName"/><el-table-column label="操作"><template #default="scope"><el-button type="primary" circle><el-icon><Edit /></el-icon></el-button><el-button type="danger" circle><el-icon><Delete /></el-icon></el-button></template></el-table-column></el-table></div><div style="margin-top: 10px"><el-paginationv-model:current-page="data.pageNum"v-model:page-size="data.pageSize":page-sizes="[5, 10, 15, 20]"layout="total, sizes, prev, pager, next, jumper":total="data.total"/></div></div></div> </template><script setup>import {Delete, Edit, Search} from "@element-plus/icons-vue"; import {reactive} from "vue"; import request from "@/utils/request.js";const data = reactive({name:'',pageNum:1,pageSize:10,total:0,EmployeeList:[],})const load = () =>{//給后端發起request請求request.get("employee/selectPage",{ //參數示例:pageNum=xxx&pageSize=xxxparams:{pageNum:data.pageNum,pageSize:data.pageSize,}}).then(res=>{/*console.log(res.data)*/data.EmployeeList = res.data.listdata.total = res.data.total}) }load()</script>
ElementUI的Pagination分頁事件(@size-change、@current-change)。
<div style="margin-top: 10px"><el-pagination@current-change="load"@size-change="load"v-model:current-page="data.pageNum"v-model:page-size="data.pageSize":page-sizes="[5, 10, 15, 20]"layout="total, sizes, prev, pager, next, jumper":total="data.total"/> </div>
- 分頁查詢的頁面渲染效果。
<5>條件查詢。
后端接口使用Employee對象接收參數。
/*** 查詢所有員工* 查詢使用get請求*/@GetMapping("/selectAll")public Result selectAll(Employee employee){List<Employee> emList = employeeService.selectAll(employee);return Result.success(emList);}/*** 分頁查詢* @param employee 對象。接收前端傳遞的屬性值* @param pageNum 當前頁碼。默認值1* @param pageSize 每頁數據個數。默認值10* @return*/@GetMapping("/selectPage")public Result selectPage(Employee employee,@RequestParam(defaultValue = "1") Integer pageNum,@RequestParam(defaultValue = "10") Integer pageSize){PageInfo<Employee> employeePageInfo = employeeService.selectPage(employee,pageNum, pageSize);return Result.success(employeePageInfo);}
- service層。
public List<Employee> selectAll(Employee employee) {return employeeMapper.selectAll(employee);}/***service層實現分頁操作的代碼*/public PageInfo<Employee> selectPage(Employee employee,Integer pageNum,Integer pageSize) {//開啟分頁查詢(傳參:當前頁碼、每頁分頁個數)PageHelper.startPage(pageNum,pageSize);//查詢所有的數據List<Employee> employeeList = employeeMapper.selectAll(employee);//PageInfo執行分頁操作return PageInfo.of(employeeList);}
- EmployeeMapper。
package com.hyl.mapper;import com.hyl.entity.Employee;import java.util.List;public interface EmployeeMapper {List<Employee> selectAll(Employee employee);}
EmployeeMapper。(動態SQL條件查詢)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hyl.mapper.EmployeeMapper"><!--動態條件查詢:如果有姓名就跟據姓名模糊查詢,且根據id倒序展示數據(數據新增的放在zuiqm)--><select id="selectAll" resultType="com.hyl.entity.Employee">select * from `employee`<where><if test="name != null">name like concat('%',#{name},'%')</if></where>order by id desc</select></mapper>
<6>重置(reset)操作。
<el-button type="warning" style="margin-left: 10px" @click="reset">重 置</el-button>
//重置輸入框操作方法 const reset = () =>{data.name = null//重新渲染數據load() }
(2)新增。(Dialog對話框)
- 簡單教程:Vue3實戰學習(Element-Plus常用組件的使用(輪播圖、日期時間選擇器、表格、分頁組件、對話框)(超詳細))(下)(6)_vuejs30 + elementplus自定義組件實戰-CSDN博客
<1>新增對話框(彈窗)組件代碼示例。
<el-dialog title="員工信息" v-model="data.formVisible" width="500"><el-form :model="data.form" label-width="80px" style="padding-right: 50px;padding-top: 20px"><el-form-item label="名稱"><el-input v-model="data.form.name" autocomplete="off" placeholder="請輸入名稱"/></el-form-item><el-form-item label="性別"><el-radio-group v-model="data.form.sex"><el-radio value="男">男</el-radio><el-radio value="女">女</el-radio></el-radio-group></el-form-item><el-form-item label="工號"><el-input v-model="data.form.no" autocomplete="off" placeholder="請輸入工號"/></el-form-item><!-- 設置最小年齡18 最大年齡100 --><el-form-item label="年齡"><el-input-number v-model="data.form.age" :min="18" :max="100" style="width: 250px" autocomplete="off" placeholder="年齡>=18與年齡<=100"/></el-form-item><!-- 設置類型:文本域 :rows設置默認顯示三行 --><el-form-item label="個人簡介"><el-input type="textarea" :rows="3" v-model="data.form.description" autocomplete="off" placeholder="請輸入個人簡介"/></el-form-item></el-form><template #footer><div class="dialog-footer"><el-button @click="data.formVisible = false">取消</el-button><el-button type="primary" @click="save">保存</el-button></div></template></el-dialog>
import {reactive} from "vue";const data = reactive({formVisible: false,form:{}, })
- 頁面渲染效果。
<2>新增按鈕添加事件。
<el-button type="primary" style="margin-left: 10px" @click="handleAdd">新 增</el-button>
import {reactive} from "vue";const data = reactive({name:'',pageNum:1,pageSize:10,total:0,EmployeeList:[],formVisible: false,form:{}, })const handleAdd = () =>{//顯示新增對話框data.formVisible = true//防止有臟數據data.form ={} }
<3>對話框新增點擊保存,調用save方法。("/employee/add")
- 代碼示例。
import {reactive} from "vue"; import request from "@/utils/request.js"; import {ElMessage} from "element-plus";const data = reactive({formVisible: false,form:{}, })const save = () =>{request.post("/employee/add",data.form).then(res=>{if(res.code === '200'){//操作成功,關閉彈窗data.formVisible=falseElMessage.success('操作成功')//新增后重新加載最新數據load()}else {//操作失敗,關閉彈窗data.formVisible=falseElMessage.error(res.msg)}}) }
<4>后端代碼示例。
- 新增接口。(controller)
package com.hyl.controller;import com.hyl.common.Result; import com.hyl.entity.Employee; import com.hyl.service.EmployeeService; import jakarta.annotation.Resource; import org.springframework.web.bind.annotation.*;import java.util.List;@RestController @RequestMapping("/employee") public class EmployeeController {@Resourceprivate EmployeeService employeeService;/***新增操作*/@PostMapping("/add")public Result add(@RequestBody Employee employee){employeeService.add(employee);return Result.success();}}
- service層。
package com.hyl.service;import com.hyl.entity.Employee; import com.hyl.mapper.EmployeeMapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Service;import java.util.List;@Service public class EmployeeService {@Resourceprivate EmployeeMapper employeeMapper;public void add(Employee employee) {employeeMapper.insert(employee);}}
- EmployeeMapper。
package com.hyl.mapper;import com.hyl.entity.Employee;import java.util.List;public interface EmployeeMapper {void insert(Employee employee); }
- EmployeeMapper.xml。
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hyl.mapper.EmployeeMapper"><insert id="insert" parameterType="com.hyl.entity.Employee">insert into `employee`(name,sex,no,age,description,department_id)values (#{name},#{sex},#{no},#{age},#{description},#{departmentId})</insert></mapper>
新增時頁面渲染效果。
(3)更新(編輯)。(表格操作欄的“編輯”)
<1>替換操作欄“編輯”、“刪除”樣式。(鏈接文字按鈕:link)
- 官方文檔。
- 代碼示例。
<el-table-column label="操作"><template #default="scope"><el-button link type="primary"><el-icon><Edit /></el-icon>編輯</el-button><el-button link type="danger"><el-icon><Delete /></el-icon>刪除</el-button></template></el-table-column>
- 頁面渲染效果。
<2>“編輯”操作綁定事件handleUpdate(scope.row)函數。
- 將操作的行對象拿來渲染表單——用于更新員工信息。
<el-table-column label="操作"><template #default="scope"><el-button link type="primary" @click="handleUpdate(scope.row)"><el-icon><Edit /></el-icon>編輯</el-button><el-button link type="danger"><el-icon><Delete /></el-icon>刪除</el-button></template></el-table-column>
行對象(scope.row)的淺拷貝問題。(錯誤!)
//更新(編輯)操作 const handleUpdate = (row) =>{//行對象的淺拷貝問題data.form = rowdata.formVisible = true }
- 這樣的設計寫法法是有問題的。當我點擊編輯按鈕,頁面渲染出員工信息編輯彈窗。
- 當我修改了某一個值,但沒有點“保存”,點擊“取消”。正常情況不會修改數據,但對象淺拷貝問題將當前的行對象也進行了修改。如下所示。
行對象的深拷貝。(JSON.stringify()、JSON.parse())
- JSON.stringify(row)會把row行對象轉換為JSON 字符串,接著使用JSON.parse()再將這個JSON 字符串轉換回一個新對象。
- 這個過程中會創建一個新的對象。新對象和原始的row行對象在內存中是相互獨立的。其中對data.form進行修改不會影響原始的row行對象。
- 代碼示例如下。
import {reactive} from "vue";const data = reactive({formVisible: false,form:{}, })//更新(編輯)操作 const handleUpdate = (row) =>{/*//行對象的淺拷貝問題data.form = row*///深拷貝一個新的對象用于編輯。這樣就不會影響行對象data.form = JSON.parse(JSON.stringify(row))data.formVisible = true }
- 再次測試。“取消”編輯時,行對象對應的數據并沒有被影響或修改。
<3>區分新增操作的"保存"與編輯操作的"保存"。(post與put請求)
- 將保存按鈕綁定事件的save函數添加條件判斷。判斷:操作的行對象是否有id。因為新增時員工沒有id、編輯(更新)時員工已經存在id。
- 代碼示例如下。
<script setup>import {Delete, Edit, Search} from "@element-plus/icons-vue"; import {reactive} from "vue"; import request from "@/utils/request.js"; import {ElMessage} from "element-plus";const data = reactive({name:'',pageNum:1,pageSize:10,total:0,EmployeeList:[],formVisible: false,form:{}, })const load = () =>{//給后端發起request請求request.get("employee/selectPage",{ //參數示例:pageNum=xxx&pageSize=xxxparams:{pageNum:data.pageNum,pageSize:data.pageSize,name:data.name}}).then(res=>{/*console.log(res.data)*/data.EmployeeList = res.data.listdata.total = res.data.total}) }//重置輸入框操作方法 const reset = () =>{data.name = null//重新渲染數據load() }//新增操作 const handleAdd = () =>{//顯示新增對話框data.formVisible = true//防止有臟數據data.form ={} }//更新(編輯)操作 const handleUpdate = (row) =>{/*//行對象的淺拷貝問題data.form = row*///深拷貝一個新的對象用于編輯。這樣就不會影響行對象data.form = JSON.parse(JSON.stringify(row))data.formVisible = true }//對話框的保存按鈕事件 const save = () =>{//有id進行更新操作。無id進行新增操作data.form.id ? update() : add() }//新增方法。新增的行對象不存在id。 const add = () => {request.post("/employee/add",data.form).then(res=>{if(res.code === '200'){//操作成功,關閉彈窗data.formVisible=falseElMessage.success('操作成功')//新增后重新加載最新數據load()}else {//操作失敗,關閉彈窗data.formVisible=falseElMessage.error(res.msg)}}) }//編輯(更新)方法 。編輯的行對象存在id const update = () =>{request.put("/employee/update",data.form).then(res=>{if(res.code === '200'){//操作成功,關閉彈窗data.formVisible=falseElMessage.success('操作成功')//更新后重新加載最新數據load()}else {//操作失敗,關閉彈窗data.formVisible=falseElMessage.error(res.msg)}}) } load()</script>
- 后端代碼示例。
/*** 更新數據*/@PutMapping("/update")public Result update(@RequestBody Employee employee){employeeService.update(employee);return Result.success();}
public void update(Employee employee) {//在數據庫是根據id更新員工信息employeeMapper.updateById(employee);}
void updateById(Employee employee);
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hyl.mapper.EmployeeMapper"><update id="updateById" parameterType="com.hyl.entity.Employee">update `employee` set name = #{name},sex=#{sex},no=#{no},age=#{age},description=#{description},department_id=#{departmentId}where id = #{id}</update> </mapper>
- 編輯(更新)操作示例。(頁面渲染效果)
(4)刪除。(表格操作欄的“刪除”)
<1>單個刪除。
- 代碼示例。
<el-table-column label="操作"><template #default="scope"><el-button link type="primary" @click="handleUpdate(scope.row)"><el-icon><Edit /></el-icon>編輯</el-button><el-button link type="danger" @click="del(scope.row.id)"><el-icon><Delete /></el-icon>刪除</el-button></template> </el-table-column>
//刪除方法(根據id刪除) const del = (id) =>{request.delete("/employee/deleteById/"+id).then(res=>{if(res.code === '200'){ElMessage.success('操作成功')//刪除后重新加載最新數據load()}else {ElMessage.error(res.msg)}}) }
“刪除”的二次確認操作。(ElMessageBox.confirm())
import {ElMessage, ElMessageBox} from "element-plus";//刪除方法(根據id刪除) const del = (id) =>{ElMessageBox.confirm('刪除數據后無法恢復,您確認刪除嗎?','刪除確認',{type: 'warning'}).then(()=>{request.delete("/employee/deleteById/"+id).then(res=>{if(res.code === '200'){ElMessage.success('操作成功')//刪除后重新加載最新數據load()}else {ElMessage.error(res.msg)}})}).catch() }
- 后端刪除接口與其它層代碼示例。
/***根據id刪除員工*/@DeleteMapping("/deleteById/{id}")public Result deleteById(@PathVariable Integer id){employeeService.deleteById(id);return Result.success();}
public void deleteById(Integer id) {employeeMapper.deleteById(id);}
@Delete("delete from `employee` where id = #{id}")void deleteById(Integer id);
- 頁面刪除操作時渲染效果。
<2>批量刪除。(type="selection")
- 官方文檔。
使用@selection-change="xxx函數"。(獲取所選行對象)
<el-table :data="data.EmployeeList" stripe @selection-change="handleSelectionChange" style="width: 100%"><el-table-column type="selection" width="55" /><el-table-column label="名稱" prop="name"/><el-table-column label="性別" prop="sex"/><el-table-column label="工號" prop="no"/><el-table-column label="年齡" prop="age"/><el-table-column label="個人簡介" prop="description" show-overflow-tooltip/><el-table-column label="部門" prop="departmentName"/><el-table-column label="操作"><template #default="scope"><el-button link type="primary" @click="handleUpdate(scope.row)"><el-icon><Edit /></el-icon>編輯</el-button><el-button link type="danger" @click="del(scope.row.id)"><el-icon><Delete /></el-icon>刪除</el-button></template></el-table-column> </el-table>
//批量選擇 const handleSelectionChange = (rows) =>{ //返回選中的行對象數組console.log(rows) }
使用map函數提取返回的數組中所選中行對象的id。
import {reactive} from "vue";//批量選擇 const handleSelectionChange = (rows) =>{ //返回選中的行對象數組console.log(rows)//從選中的行對象中取出所有的id,組成一個新數組!//使用map函數(數組內置函數)//遍歷rows數組,將每個元素(行對象)的id屬性值提取出來,組成一個新的數組。并賦值給存儲id的數組中data.ids = rows.map(row => row.id)console.log(data.ids) }
批量刪除的后端接口代碼。(controller)
- 后端接口必須使用注解@RequestBody接受前端數組傳參。
/***批量刪除員工信息*/@DeleteMapping("/deleteBatch")public Result deleteBatch(@RequestBody List<Integer> ids){employeeService.deleteBatch(ids);return Result.success();}
service層。(依次調用deleteById)
public void deleteById(Integer id) {employeeMapper.deleteById(id);}public void deleteBatch(List<Integer> ids) {for (Integer id : ids) {//依次根據員工id刪除this.deleteById(id);}}
前端代碼示例。
<div class="card" style="margin-bottom: 5px"><el-button type="primary" style="margin-left: 10px" @click="handleAdd">新 增</el-button><el-button type="danger" style="margin-left: 10px" @click="delBatch">批量刪除</el-button><el-button type="info" style="margin-left: 10px">導 入</el-button><el-button type="success" style="margin-left: 10px">導 出</el-button></div>
import {reactive} from "vue"; import request from "@/utils/request.js"; import {ElMessage, ElMessageBox} from "element-plus";const data = reactive({ids:[] })//批量刪除 const delBatch = () => {//如果沒有選中表格項,則提示錯誤if (data.ids.length === 0) {ElMessage.warning('請選中需刪除的數據')return}ElMessageBox.confirm('批量刪除數據后無法恢復,您確認刪除嗎?','批量刪除確認',{type:'warning'}).then(()=>{request.delete("/employee/deleteBatch", {data: data.ids}).then(res => {if(res.code === '200'){ElMessage.success('操作成功')//刪除后重新加載最新數據load()}else {ElMessage.error(res.msg)}})}).catch() }
- 當沒選中表格項,進行批量刪除的頁面渲染效果。
- 選中表格的某幾個選單項。進行批量刪除操作。
- 到這里就算SpringBoot3+Vue3實現基本增刪改查的完結。還需要自己再琢磨琢磨很多新的知識!