SpringBoot3實戰(SpringBoot3+Vue3基本增刪改查、前后端通信交互、配置后端跨域請求、數據批量刪除(超詳細))(3)

目錄

一、從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實現基本增刪改查的完結。還需要自己再琢磨琢磨很多新的知識!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/73183.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/73183.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/73183.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

單播、廣播、組播和任播

文章目錄 一、單播二、廣播三、組播四、任播代碼示例&#xff1a; 五、各種播的比較 一、單播 單播&#xff08;Unicast&#xff09;是一種網絡通信方式&#xff0c;它指的是在網絡中從一個源節點到一個單一目標節點對的傳輸模式。單播傳輸時&#xff0c;數據包從發送端直接發…

【實戰】deepseek數據分類用戶評論數據

在平時的工作中&#xff0c;我們會遇到數據分類的情況&#xff0c;比如將一些文本劃分為各個標簽。如果人工分類這塊的工作量將是非常大&#xff0c;而且分類數據的準確性也不高。我們需要用到一些工具來實現。提高效率的同時也提高準確率。 1.示例數據 用戶ID 時間戳 評論場…

技術視角解讀:游戲出海如何借助AWS全球架構突破性能與合規瓶頸

【場景痛點】 某二次元卡牌手游團隊在東南亞市場遭遇聯機延遲投訴率高達37%&#xff0c;日本地區因數據合規問題面臨下架風險。在傳統IDC架構下&#xff0c;運維團隊需要同時管理3個區域的物理服務器&#xff0c;版本更新耗時長達6小時。 【技術架構升級】 通過AWS Local Zones…

【JavaEE】網絡編程socket

1.????前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 親愛的朋友們&#x1f44b;&#x1f44b;&#xff0c;這里是E綿綿呀????。 如果你喜歡這篇文章&#xff0c;請別吝嗇你的點贊????和收藏&#x1f4d6;&#x1f4d6;。如果你對我的…

第16屆藍橋杯單片機4T模擬賽三

本次模擬賽涉及的模塊&#xff1a;基礎三件套&#xff08;Led&Relay&#xff0c;按鍵、數碼管&#xff09; 進階單件套&#xff08;pcf8591的AD模塊&#xff09; 附件&#xff1a; 各模塊底層代碼在文章的結尾 一、數碼管部分 1.頁面1 頁面1要顯示的格式是&#xff1a; …

網絡華為HCIA+HCIP IPv6

目錄 IPv4現狀 IPv6基本報頭 IPv6擴展報頭 IPv6地址 IPv6地址縮寫規范 ?編輯 IPv6地址分配 IPv6單播地址分配 IPv6單播地址接口標識 IPv6常見單播地址 - GUA &#xff08;2 / 3 開頭&#xff09; IPv6常見單播地址 - ULA IPv6常見單播地址 - LLA IPv6組播地…

基于YOLOv8深度學習的智能小麥害蟲檢測識別系統

作者簡介&#xff1a;Java領域優質創作者、CSDN博客專家 、CSDN內容合伙人、掘金特邀作者、阿里云博客專家、51CTO特邀作者、多年架構師設計經驗、多年校企合作經驗&#xff0c;被多個學校常年聘為校外企業導師&#xff0c;指導學生畢業設計并參與學生畢業答辯指導&#xff0c;…

Mac:Maven 下載+安裝+環境配置(詳細講解)

&#x1f4cc; 下載 Maven 下載地址&#xff1a;https://maven.apache.org/download.cgi &#x1f4cc; 無需安裝 Apache官網下載 Maven 壓縮包&#xff0c;無需安裝&#xff0c;下載解壓后放到自己指定目錄下即可。 按我自己的習慣&#xff0c;我會在用戶 jane 目錄下新建…

XSS-labs(反射型XSS) 靶場 1-13關 通關

目錄 前言 XSS漏洞概述 XSS漏洞分類 通關日記 level1 分析 解題 ?level2 分析 解題 方法一&#xff1a;閉合標簽 方法二&#xff1a;閉合雙引號 level3 分析 解題 level4 分析 解題 level5 分析 解題 level6 分析 解題 level7 分析 解體 level8 …

GPT-5 將免費向所有用戶開放?

GPT-5 將免費向所有用戶開放&#xff1f; 硅谷知名分析師 Ben Thompson 最近與 OpenAI CEO Sam Altman 進行了一場深度對談&#xff0c;其中Sam Altman透漏GPT-5將免費向大家發放。 OpenAI 這波操作可不是一時沖動&#xff0c;而是被逼出來的。DeepSeek 這個新秀橫空出世&am…

【雜記二】git, github, vscode等

一、前言 暫時空著... 二、git 2.1 可能的疑問 1. VSCode 項目名和 GitHub 倉庫名是否需要一致&#xff1f; 不需要一致。 VSCode 項目名&#xff08;也就是你本地的文件夾名字&#xff09;和 GitHub 倉庫名可以不一樣。 Git 是一個分布式版本控制系統&#xff0c;它主要關…

數學愛好者寫的編程系列文章

作為一個數學愛好者&#xff0c;我大學讀的專業卻不是數學專業&#xff0c;而是跟計算機有關的專業。原本我對編程一竅不通&#xff0c;平時上課也是在看數學文獻&#xff0c;作業基本靠同學&#xff0c;考試及格就行。不過后來因為畢業的壓力&#xff0c;我還是擁抱編程了&…

FPGA 以太網通信(四)網絡視頻傳輸系統

一、網絡視頻傳輸系統 網絡視頻傳輸系統使用ov5640攝像頭采集數據&#xff0c;通過組件UDP幀將視頻數據實時傳輸給上位機。 ov5640視頻傳輸帶寬 像素分辨率設為640x480&#xff0c;幀率設為60幀&#xff0c;像素格式為RGB565&#xff0c;傳輸帶寬為 640 x 480 x 16bit x 60 fps…

[leetcode]1631. 最小體力消耗路徑(bool類型dfs+二分答案/記憶化剪枝/并查集Kruskal思想)

題目鏈接 題意 給定 n m n\times m nm地圖 要從(1,1) 走到 (n,m) 定義高度絕對差為四聯通意義下相鄰的兩個點高度的絕對值之差 定義路徑的體力值為整條路徑上 所有高度絕對差的max 求所有路徑中 最小的路徑體力值是多少 方法1 這是我一開始自己寫的記憶化剪枝 比較暴力 時…

DeepSeek寫打臺球手機小游戲

DeepSeek寫打臺球手機小游戲 提問 根據提的要求&#xff0c;讓DeepSeek整理的需求&#xff0c;進行提問&#xff0c;內容如下&#xff1a; 請生成一個包含以下功能的可運行移動端打臺球小游戲H5文件&#xff1a; 要求 可以重新開始游戲 可以暫停游戲 有白球和其他顏色的球&am…

webpack使用詳細步驟

項目描述 本項目 webpack 的基本使用。 webpack 官方&#xff1a;https://webpack.docschina.org/concepts/ Element-plus 官方&#xff1a;https://element-plus.sxtxhy.com/zh-CN/ Vue3 官方&#xff1a;https://cn.vuejs.org/ 項目組成明細 每個步驟完成后重新執行 npm run …

【STM32實物】基于STM32的太陽能充電寶設計

基于STM32的太陽能充電寶設計 演示視頻: 基于STM32的太陽能充電寶設計 硬件組成: 系統硬件包括主控 STM32F103C8T6、0.96 OLED 顯示屏、蜂鳴器、電源自鎖開關、溫度傳感器 DS18B20、繼電器、5 V DC 升壓模塊 、TB4056、18650鋰電池、9 V太陽能板、穩壓降壓 5 V三極管。 功能…

【記一次】AI微調訓練步數計算方式

llama微調訓練步數計算方式,以下數據為假設 一、關鍵參數解析 總樣本數&#xff1a;Num examples 1,047 表示訓練數據集包含 1,047 個樣本。 訓練輪數&#xff1a;Num Epochs 300 表示整個訓練集將被遍歷 300 次。 總批次大小&#xff1a;Total train batch size 80 表示…

python-selenium 爬蟲 由易到難

本質 python第三方庫 selenium 控制 瀏覽器驅動 瀏覽器驅動控制瀏覽器 推薦 edge 瀏覽器驅動&#xff08;不容易遇到版本或者兼容性的問題&#xff09; 驅動下載網址&#xff1a;鏈接: link 1、實戰1 &#xff08;1&#xff09;安裝 selenium 庫 pip install selenium&#…

yaffs

YAFFS&#xff08;Yet Another Flash File System&#xff09;是專為NAND閃存設計的日志結構文件系統&#xff0c;其核心原理圍繞NAND閃存的特性優化數據管理。以下是其關鍵原理的詳細說明&#xff1a; 1. NAND閃存適配 寫入限制&#xff1a;NAND閃存需按頁寫入&#xff08;通…