网页设计教程免费下载/seo基础视频教程

网页设计教程免费下载,seo基础视频教程,小型公司网络建设方案,php创建网页目录 一、从0快速搭建SpringBoot3工程、SpringBoot3集成MyBatis、PageHelper分页查询的详细教程。(博客链接) 二、实现前端与后端通信对接数据。(axios工具) &#xff08;1&#xff09;安装axios。(vue工程目录) &#xff08;2&#xff09;封装请求工具类。(request.js) <1&…

目录

一、从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.mzph.cn/pingmian/73183.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单播、广播、组播和任播

文章目录 一、单播二、广播三、组播四、任播代码示例&#xff1a; 五、各种播的比较 一、单播 单播&#xff08;Unicast&#xff09;是一种网络通信方式&#xff0c;它指的是在网络中从一个源节点到一个单一目标节点对的传输模式。单播传输时&#xff0c;数据包从发送端直接发…

【实战】deepseek数据分类用户评论数据

在平时的工作中&#xff0c;我们会遇到数据分类的情况&#xff0c;比如将一些文本划分为各个标签。如果人工分类这块的工作量将是非常大&#xff0c;而且分类数据的准确性也不高。我们需要用到一些工具来实现。提高效率的同时也提高准确率。 1.示例数据 用户ID 时间戳 评论场…

【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 …

【杂记二】git, github, vscode等

一、前言 暂时空着... 二、git 2.1 可能的疑问 1. VSCode 项目名和 GitHub 仓库名是否需要一致&#xff1f; 不需要一致。 VSCode 项目名&#xff08;也就是你本地的文件夹名字&#xff09;和 GitHub 仓库名可以不一样。 Git 是一个分布式版本控制系统&#xff0c;它主要关…

FPGA 以太网通信(四)网络视频传输系统

一、网络视频传输系统 网络视频传输系统使用ov5640摄像头采集数据&#xff0c;通过组件UDP帧将视频数据实时传输给上位机。 ov5640视频传输带宽 像素分辨率设为640x480&#xff0c;帧率设为60帧&#xff0c;像素格式为RGB565&#xff0c;传输带宽为 640 x 480 x 16bit x 60 fps…

DeepSeek写打台球手机小游戏

DeepSeek写打台球手机小游戏 提问 根据提的要求&#xff0c;让DeepSeek整理的需求&#xff0c;进行提问&#xff0c;内容如下&#xff1a; 请生成一个包含以下功能的可运行移动端打台球小游戏H5文件&#xff1a; 要求 可以重新开始游戏 可以暂停游戏 有白球和其他颜色的球&am…

【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&#…

git的底层原理

git的底层原理 三段话总结git&#xff0c; 1. 工作原理&#xff1a;git管理是一个DAG有向无环图&#xff0c;HEAD指针指向branch或直接指向commit&#xff0c;branch指向commit&#xff0c;commit指向tree&#xff0c;tree指向别的tree或直接指向blob。 2. git所管理的一个目录…

神聖的綫性代數速成例題13. 非齊次方程組解的性質、非齊次方程組解的討論

綫性空間的維數&#xff1a; 若綫性空間中存在一組綫性無關的矢量&#xff0c;使得中的任意矢量 都可以由綫性表示&#xff0c;則稱為綫性空間的維數&#xff0c;記作&#xff0c;稱為的一組基。 基與座標變換&#xff1a; 設和是維綫性空間的兩組基&#xff0c;且&#xff0c;…

Kafka集成Debezium监听postgresql变更

下载postgres的插件&#xff1a;https://debezium.io/documentation/reference/2.7/install.html 2.7版本支持postgresql12数据库。 debezium-connector-postgres-2.7.4.Final-plugin.tar.gz 上传插件并解压 mkdir /usr/local/kafka/kafka_2.12-2.2.1/connector cd /usr/local…

『uniapp』简单文本复制文字 富文本内容复制文字(详细图文注释)

目录 text组件错误代码示例成功代码总结 欢迎关注 『uniapp』 专栏&#xff0c;持续更新中 欢迎关注 『uniapp』 专栏&#xff0c;持续更新中 text组件 官方文档可知app端用selectable可实现文本选中进而可复制,也就是说text标签内部的文本就可以复制了 https://uniapp.dclou…

算法模型从入门到起飞系列——背包问题(探索最大价值的掘金之旅)

文章目录 前言一、背包问题溯源&#xff08;动态规划&#xff09;1.1 动态规划的概念1.2 动态规划的基本步骤1.3 动态规划的实际应用 二、背包问题2.1 背包问题衍生2.2 0-1背包2.2.1 0-1背包描述2.2.2 0-1背包图解2.2.3 0-1背包代码刨析 2.3 完全背包2.3.1 完全背包描述2.3.2 完…

Python实现爬虫:天气数据抓取(+折线图)

一、基本架构 1、URL管理器&#xff1a;爬虫的调度中枢 核心职责 功能说明URL去重防止重复抓取URL优先级管理控制抓取顺序&#xff08;广度优先/深度优先&#xff09;断点续爬支持持久化存储抓取状态分布式协同多节点共享URL队列 2、网页下载器&#xff1a;数据获取的引擎 功…