学习来源:视频p6
书接上文

目录

  • 数据修改功能
    • 修改对话框
    • 视频教程的做法
    • 后端提供接口
    • 前端调用接口
    • 修改完成后提交
  • 数据删除功能
    • 后端开设接口
    • 前端调用
  • 最终成果展示

数据修改功能

将之前的 BookManage 页面的按钮改为想要的功能

可以注意到修改按钮的标签以及绑定了事件 handleClick

点击之后其可以在控制台打印出当前行对象的内容

观看视频时,关于修改数据,弹幕分为了两派
一派认为因该直接从页面中获取现有的数据信息加以修改,再提交给后端并存储到数据库,此流程业务简单,减轻服务器负荷。
还有一派认为因该依据关键信息或唯一标识,从后台请求这一系列数据,在此基础上进行修改,再提交给后端并存储到数据库,此流程数据安全。

我认为确实应该从后端拿数据,毕竟前端显示的数据不一定是完整信息,最全最新的内容肯定是在数据库当中,所有从后端拿数据重新修订再保存到数据库更加安全严谨。

相较于视频中新增一个页面的方式,我选择以弹出框来展示修改页面,这样我认为更切合实际场景

修改对话框

其核心内容就是 dialogFormVisible 这个属性在点击关键字时改为 true(默认是false)

所以运用到原来的页面上,当点击“修改”时,把这个属性置为 true 即可

弹出的表单用原来的新增页面进行代码结合复用
将一下代码拆分放入对应位置即可

<template><div><el-button type="text" @click="dialogFormVisible = true">修改 Dialog</el-button><el-dialog title="修改" :visible.sync="dialogFormVisible"><el-form style="width: 80%" :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm"><el-form-item label="书名" prop="name"><el-input v-model="ruleForm.name"></el-input></el-form-item><el-form-item label="作者" prop="author"><el-input v-model="ruleForm.author"></el-input></el-form-item><el-form-item><el-button type="primary" @click="submitForm('ruleForm')">立即创建</el-button><el-button @click="resetForm('ruleForm')">重置</el-button></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogFormVisible = false">取 消</el-button><el-button type="primary" @click="dialogFormVisible = false">确 定</el-button></div></el-dialog></div></template><script>export default {data() {return {dialogFormVisible: false,formLabelWidth: '120px',ruleForm: {name: '',author: ''},rules: {name: [{ required: true, message: '书名不能为空', trigger: 'blur' }],author: [{ required: true, message: '作者不能为空', trigger: 'blur' }],}};},methods: {submitForm(formName) {const _this = this;this.$refs[formName].validate((valid) => {if (valid) {axios.post("http://localhost:8181/book/save",this.ruleForm).then(function (resp) {if (resp.data == "success"){_this.$alert("《"+_this.ruleForm.name+"》添加成功", '成功', {confirmButtonText: '确定',callback: action => {_this.$router.push("/BookMange");}});}else{_this.$message.error("添加失败");}})} else {console.log('添加失败');return false;}});},resetForm(formName) {this.$refs[formName].resetFields();},}}</script>

最终效果如下

视频教程的做法

创建额外的页面,当点击修改按钮时,进行页面跳转,并用 query 传递操作的 id 信息

handleClick(row) {this.$router.push({path: '/update',query:{id: row.id}})},


在新的页面初始化地方进行接收参数,请求后端数据

需要跳转用 $router ,需要接收参数用 $route

拓展阅读
route 和 router的区别
params 和 query 传递参数的区别

后端提供接口

之前 bookRepository 继承的 JPA 接口中,也已经写好了 findById() 函数,对我们来说相当方便,只是这个接口返回的对象是 Optional 的对象,其可以把空的对象也能正常包装并返回,避免出现空指针异常导致程序崩溃,Optional讲解

再调用 get() 方法以获取到对象,结果也是能正确输出的
则下一步写入handler接口供外部调用

@GetMapping("/findById/{id}")public Book findById(@PathVariable("id") Integer id){return bookRepository.findById(id).get();}


经测试也是可以使用的,故在前端调用

前端调用接口

当点击 修改 操作时,对调用函数 handleClick 进行修改

handleClick(row) {const _this = this;this.dialogFormVisible = true;axios.get("http://localhost:8181/book/findById/"+row.id).then(function (resp) {_this.ruleForm = resp.data;})},

即可实现点击后出现弹窗+载入修改的目录信息

修改完成后提交

将之前的立即创建改成符合业务逻辑的“修改完成”

然后对函数 submitForm 改装一下即可
其实目前实际使用看来,不改装也能满足业务逻辑需求,JPA 的save函数自动帮我们把对象存进去了
JPA是判定了当前参数是否携带主键,如果没有就存入,如果有就修改内容

但为了业务严谨,并且以后可能遇到更复杂的业务逻辑,针对修改功能还是有必要专门开辟接口的
且根据 REST 规范,更新应该使用 PUT 请求
所以直接在 handler 里面新增接口

@PutMapping("/update")public String update(@RequestBody Book book){Book result = bookRepository.save(book);if (result != null){return "success";}else {return "fail";}}

将此处的 post 改为 put ,接口网址改成 update

即可实现修改功能

数据删除功能

后端开设接口

@DeleteMapping("/deleteById/{id}")public void delete(@PathVariable("id") Integer id){bookRepository.deleteById(id);}

前端调用


按钮组件绑定函数

deleteBook(row){const _this = this;axios.delete("http://localhost:8181/book/deleteById/"+row.id).then(function (resp) {if (resp.status == 200){_this.$alert("《"+row.name+"》删除成功", '成功', {confirmButtonText: '确定并刷新',callback: action => {_this.$router.go(0);}});}else{_this.$message.error("删除失败");}})},

最终成果展示

主页面js代码

<script>export default {methods: {handleClick(row) {const _this = this;this.dialogFormVisible = true;axios.get("http://localhost:8181/book/findById/"+row.id).then(function (resp) {_this.ruleForm = resp.data;})},deleteBook(row){const _this = this;axios.delete("http://localhost:8181/book/deleteById/"+row.id).then(function (resp) {if (resp.status == 200){_this.$alert("《"+row.name+"》删除成功", '成功', {confirmButtonText: '确定并刷新',callback: action => {_this.$router.go(0);}});}else{_this.$message.error("删除失败");}})},page(currentPage){const _this = this;axios.get("http://localhost:8181/book/findPart/"+currentPage+"/3").then(function (resp) {_this.tableData = resp.data.content;_this.total = resp.data.totalElements;})},submitForm(formName) {const _this = this;this.$refs[formName].validate((valid) => {if (valid) {axios.put("http://localhost:8181/book/update",this.ruleForm).then(function (resp) {if (resp.data == "success"){_this.$alert("《"+_this.ruleForm.name+"》修改成功", '成功', {confirmButtonText: '确定',callback: action => {_this.$router.go(0);}});}else{_this.$message.error("修改失败");}})} else {console.log('添加失败');return false;}});},resetForm(formName) {this.$refs[formName].resetFields();},},created(){const _this = this;axios.get("http://localhost:8181/book/findPart/1/3").then(function (resp) {_this.tableData = resp.data.content;_this.total = resp.data.totalElements;})},data() {return {total: null,tableData: null,dialogFormVisible: false,dialogFormVisible: false,formLabelWidth: '120px',ruleForm: {name: '',author: ''},rules: {name: [{ required: true, message: '书名不能为空', trigger: 'blur' }],author: [{ required: true, message: '作者不能为空', trigger: 'blur' }],}}}}</script>