前端学习04-增删改查(条件、分页)
增删改查,条件查询,分页查询,表单数据校验,传参总结
1. 查询所有学生信息(无参数)
1.1. 前后端字段统一
注意,class这个单词不能用,这是java里面的关键字;

1.2. 注释掉分页器

1.3. StudentView.vue
表格html:
| 1 |  | 
script:
| 1 |  | 
1.4. 接口总结


在页面部分:我们使用:data绑定我们的表格数据tableData。在表格中使用prop对每个字段进行对应,prop起名要和java返回值类型保持一致。
在请求部分,我们分三步走:
- 在data()中return我们的tableData,相当于声明,后面就可以定义使用了(html表格中定义的表格数据是tableData,在发起请求也是把返回值的内容赋值给tableData)。
- 在created方法中默认调用getList的方法(created方法对标onMounted,页面加载默认调用),意思是我们加载这个页面你的时候默认会调用methods里面的getList方法。
- 在methods里定义getList方法,在里面调用我们之前封装的request对象发送axios请求。然后把嵌在后端返回值里的实体数组对应上我们的表格数据tableData即可(注意后端返回的code类型是数字还是字符串)。
2. 条件查询
武哥视频35:43
思路:我们点击按钮,将输入框中的值作为参数,通过@click绑定传入到我们methods中定义好的方法,然后将查询到的数据绑定到表格数据tableData上。
- 将findByNameOrPhone方法通过@click绑定到搜索按钮  
- 在methods中定义findByNameOrPhone方法 
- 输入框绑定params对象里面的属性,记得要再data中做初始化   
- findByNameOrPhone方法中传参数  
现在我们可以直接使用findByNameOrPhone方法来代替之前的getList方法。将两个查询列表的方法合二为一,变成一个新的getList方法。
有时候前端不传递参数后端不受影响,是因为后端在设计时考虑到了参数的默认处理方式;而有的时候需要在后端显式声明参数的可选性,这取决于后端接口的设计和业务需求。
前端发送的是params对象,params对象到了会自动拆分开来,匹配到page对象和student对象中。
2.1. Ext.重置按钮
武哥54:15
创建一个按钮,点击按钮的时候先清空input框中的内容,然后调用getList方法进行查询。
- 按钮通过@Click绑定reset方法  
- 在reset方法中重置params里面的值并请求getList方法 - 需要有this  
3. 分页查询信息
3.1. Ext.注意前后端参数名对应
MybatisPlus中的pageNum是current,页容量pageSize是size。
3.2. 分页器绑定的方法与值
分析前端分页器代码(分析分页器相关绑定的方法和值)
| 1 |  | 
@size-change绑定方法handleSizeChange,我们在methods中定义,当我们切换“每页多少条”的时候会调用handleSizeChange方法;@current-change绑定方法handleCurrentChange,我们在methods中定义,当我们切换“第几页”的时候会调用handleCurrentChange方法,现在我们需要在methods中声明这两个方法。

:current-page代表当前在第几页,绑定params对象中的属性current。
:page-sizes代表每页能有多少条的选项,我们写死就好,”[10, 15, 20, 30]”
:page-size代表当前页有多少条,绑定params对象中的属性size
:total表示总共有多少页,绑定total字段
1和2是分页器根据total和pageSizes自己计算来的,不需要我们进行传值。

那么下面我们定义这些字段:

3.3. 分页器相关的方法编写
首先我们看到返回的result:

getList方法拿到返回的total:

点击current或者size的时候重新发起请求:

注意:这里的handleSizeChange和handleCurrentChange方法是回调函数,回调说明:我们点击完要看多少页,或者想看多少容量之后,默认会把我们点击的参数传到参数列表中,虽然我们上面并没有做任何的传值操作。

这里需要理解一下回调,这里是怎么对应的。
4. 新增、编辑信息
4.1. el-dialog对话框,弹窗
新的组件都放到一个新的div里面
https://element.eleme.cn/#/zh-CN/component/dialog
| 1 |  | 
4.2. 对话框是否显示
- 对话框的显示状态初始值定义   
- 额外封装方法,供其他方法操作对话框的启动或关闭 
- 封装js代码1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29//打开增加更新对话框
 openDialog(row) {
 //重置form表单属性
 this.form = {};
 this.dialogOpen = true;
 //对表单中的数据进行判断,如果有id就是更新操作,没有id就是添加操作
 if (row.id) {
 this.addOrUpdateFlag = '更新信息';
 //将表格中的数据转移到表单中
 this.form = {...row};
 } else {
 this.addOrUpdateFlag = '添加信息';
 }
 },
 //关闭增加更新对话框
 closeDialog(evt) {
 this.dialogOpen = false;
 //解决按钮点击完之后,按钮不取消聚焦问题
 let target = evt.target;
 if (target.nodeName == "SPAN") {
 target = evt.target.parentNode;
 }
 target.blur();
 },
4.3. 表单属性定义与匹配
我们定义的form对应form标签
| 1 |  | 

4.4. 关于新增与更新表单的区别
- 标题名称    
- 设置某些字段在更新中显示 
4.5. 添加,更新请求
- 按钮对应  
- 发起请求 
- js请求1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42//添加或更新方法
 addOrUpdate(evt) {
 //判断是添加还是更新
 if (this.form.id) {
 //更新
 request.post('/student/update', this.form).then(res => {
 if (res.code === 200) {
 this.alertMessage(res.msg, 'success');
 this.getList();
 this.closeDialog();
 } else {
 this.alertMessage(res.msg, 'error');
 }
 }).catch(error => {
 console.log("error:" + error);
 }
 );
 } else {
 //添加
 request.post('/student/add', this.form).then(res => {
 if (res.code === 200) {
 this.alertMessage(res.msg, 'success');
 this.getList();
 this.closeDialog();
 } else {
 this.alertMessage(res.msg, 'error');
 }
 }).catch(error => {
 console.log("error:" + error);
 }
 );
 }
 //解决按钮点击完之后,按钮不取消聚焦问题
 let target = evt.target;
 if (target.nodeName == "SPAN") {
 target = evt.target.parentNode;
 }
 target.blur();
 this.closeDialog();
 },
5. 删除信息
5.1. 页面对应

5.2. 删除请求
- 详细请求1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33// 根据id删除数据的方法
 deleteById(id) {
 // 弹出确认删除提示框
 this.$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
 confirmButtonText: '确定',
 cancelButtonText: '取消',
 type: 'warning'
 }).then(() => {
 console.log("id:" + id);
 // 用户点击确定按钮时执行的操作
 // 发起删除请求
 request.delete(`/student/${id}`)
 .then(res => {
 // 处理成功响应
 if (res.code === 200) {
 this.alertMessage(res.msg, 'success');
 this.getList();
 } else {
 this.alertMessage(res.msg, 'error');
 }
 })
 .catch(error => {
 console.log("error:" + error);
 });
 }).catch((error) => {
 // 用户点击取消按钮时执行的操作
 // 显示已取消删除的提示消息
 this.$message({
 type: 'info',
 message: error
 });
 });
 },
6. 传参详解
6.1. get方法向url传参
- 模板字符串拼接1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11const param1 = 'value1';
 const param2 = 'value2';
 const url = `/api/data?param1=${param1}¶m2=${param2}`;
 request.get(url)
 .then(response => {
 // 处理响应
 })
 .catch(error => {
 // 处理错误
 });
- 普通字符串拼接1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11const params = new URLSearchParams();
 params.append('param1', 'value1');
 params.append('param2', 'value2');
 request.get('/api/data?' + params.toString())
 .then(response => {
 // 处理响应
 })
 .catch(error => {
 // 处理错误
 });
- 传递params1 
 2
 3
 4
 5
 6
 7
 8
 9
 10request.get('/api/data', {
 params: {
 param1: 'value1',
 param2: 'value2'
 }
 }).then(response => {
 // 处理响应
 }).catch(error => {
 // 处理错误
 });
- pathVariable-字符串拼接1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15methods: {
 fetchData() {
 const userId = 123; // 假设 userId 是你要传递的参数
 const url = 'https://example.com/api/user/' + userId;
 
 // 发起 GET 请求
 request.get(url)
 .then(response => {
 // 处理响应数据
 })
 .catch(error => {
 // 处理错误
 });
 }
 }
6.2. post方法向body传参
| 1 |  | 
6.3. delete+Pathvriable传参
| 1 |  | 
6.4. post方法向url+body传参
params参数拼接在url上面,表单数据在url逗号后面进行传递
https://blog.csdn.net/qq_71214810/article/details/134565037
| 1 |  | 
7. 额外总结
7.1. Ext关于模板、插槽与传值
- 页面上将行内定义一个template,设置scope,这样能让调用的方法传参对应到每一行
- 注意这里的不能直接调用this

更新的参数对应

删除方法中参数对应

7.2. Ext关于this关键字
在Vue中,this的上下文在不同的场景下会发生变化。为了避免this失效,可以使用箭头函数、bind方法或保存this引用。这样可以确保在不同的上下文中正确地指向Vue实例。
- 我们默认this会指向vue实例
- el-table中的单条数据调用方法的时候,不能写this.方法名。因为this可能会指向el-table的上下文而不是 Vue 实例。
- 在方法中调用其他方法,需要使用this关键字
- 在模板中不推荐使用this关键字,Vue.js 通过其模板编译过程自动绑定了所有必需的数据和方法,所以你可以直接在模板中访问它们而无需 this前缀。
7.3. Ext每一条数据的id是怎么传到delete方法里面的?
答:是通过template+slot+scope.row.id来实现的
理解了,这段代码中通过使用 Vue 的模板语法和作用域插槽来传递每条数据的 ID 到 delete 方法中。让我为你详细解释一下。
- 作用域插槽: - 在 Vue 中,作用域插槽是一种特殊的插槽,它允许你访问父组件中的数据并在子组件中使用。在这个例子中,很可能是使用了 - el-table组件的作用域插槽,用于渲染表格的每一行数据。
- 
- template:这是 Vue 模板语法的一部分,用于声明模板块的起始标签。
- slot:在 Vue 中,插槽(slot)是一种占位符,允许你将任意内容插入到组件中指定的位置。
- scope.row.id:在作用域插槽中,- scope是一个对象,包含了当前渲染这个插槽的一些信息,比如当前行的数据。- scope.row就是当前行的数据对象,而- .id则是该数据对象中的一个属性,很可能是这条数据的唯一标识符(ID)。
 
- 传递到 - delete方法中:- 当点击删除按钮时,很可能是通过事件处理器调用了 - delete方法,并将当前行的 ID 作为参数传递给了该方法。在 Vue 中,事件处理器可以通过- @click指令来绑定到 HTML 元素上,并通过方法调用来触发。
所以,总的来说,通过作用域插槽将每一条数据的 ID 传递到 delete 方法中,使得在删除操作时可以准确地操作对应的数据。
7.4. Ext对象属性值copy
点击按钮的时候,需要我们将scope里面的row的属性复制到form中,这样表单就能显示我们已经有的数据了

7.5. Ext每次打开对话框之前置空
如果不置空会出现问题,比如我们打开一个信息的编辑页,form中就已经有值了,但是再次打开新增,表单中还是会有值(添加完一个数据之后,表单中的值会自动清空的)

7.6. 按钮点击完不取消聚焦问题
把下面这段代码放在按钮@click的方法对应的方法中的最后。
| 1 |  | 
7.7. 前端的中间弹窗和上面弹窗记录
消息提示Message
https://element.eleme.cn/#/zh-CN/component/message
文档中展示的是$版本,可以直接在方法中使用,另外还有调用对象的方式来进行消息提示。
代码如下(但是推荐使用文档版本)
| 1 |  | 
弹框MessageBox
https://element.eleme.cn/#/zh-CN/component/message-box
弹框是纯放在方法代码里面就行,可以用在删除之前进行弹框确认,示范代码如下:
不用再then里面传参数,then的箭头右边直接共享方法传进来的参数
| 1 |  | 
7.8. 关于true-false属性值问题
以dialog标签的title和show-close属性举例。
| 1 |  | 
- 无论是否有额外定义属性值,我们前面都要加上冒号声明绑定。这个绑定并不是纯为了传参用的,而是为了让值与标签属性绑定上。
7.9. 小知识点
- 无参数情况,可以省略括号
- 定义属性和方法,后面可以直接加逗号
- !important高优先级
7.10. 插槽自定义属性
title和content本来是el-page-header的属性,通过插槽可以进行向下的高级自定义
| 1 |  | 
8. 校验规则
8.1. 输入框必填校验


8.2. 重新打开输入框,必填校验还在哪里提示
添加dialog的属性,关闭对话框摧毁元素。

设置打开dialog的方法,在最开始设置form为空

8.3. 提交按钮绑定校验

下面这里要注意传参穿的是字符串,要加上引号啊!


8.4. 数字校验
在自定义的基础上添加两点:

