在任务六中我们讲过,前后端跨域数据交互,有两种方式可以解决跨域请求,任务六我们使用了CorsConfig类配置跨域。本次任务,我们使用一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中的axios,实现前后端跨域数据交互。通过本次任务,大家能够:
(1)掌握axios的使用方法,包括全局设置;
(2)Element中
(3)指定记录删除,以及批量数据删除;
(4)Element中
目前我们的前端页面还没有变,仍然沿用最初的home页面,下一个任务中我们将进行VUE路由设计,主要对侧边栏进行维护,届时将对页面的逻辑进行调整。
axios首先需要安装,如果VUE项目正在运行,请使用CTRL+C,然后点击Y终止运行,然后的终端输入:
npm i axios -s
安装成功后,大家可以看到axios的版本
引入axios封装到request中。新建一个utils文件夹,新建request.js。
配置文件request.js代码如下。
import axios from 'axios' const request = axios.create({ baseURL: '/api', // 注意!! 这里是全局统一加上了 '/api' 前缀,也就是说所有接口都会加上'/api'前缀在,页面里面写接口的时候就不要加 '/api'了,否则会出现2个'/api',类似 '/api/api/user'这样的报错,切记!!! timeout: 5000 }) // request 拦截器 // 可以自请求发送前对请求做一些处理 // 比如统一加token,对请求参数统一加密 request.interceptors.request.use(config => { config.headers['Content-Type'] = 'application/json;charset=utf-8'; // config.headers['token'] = user.token; // 设置请求头 return config }, error => { return Promise.reject(error) }); // response 拦截器 // 可以在接口响应后统一处理结果 request.interceptors.response.use( response => { let res = response.data; // 如果是返回的文件 if (response.config.responseType === 'blob') { return res } // 兼容服务端返回的字符串数据 if (typeof res === 'string') { res = res ? JSON.parse(res) : res } return res; }, error => { console.log('err' + error) // for debug return Promise.reject(error) } ) export default request
说明: 关于baseURL我们稍后经过对比之后在进行更改。
两行代码为:
import request from '@/utils/request'//添加 Vue.prototype.request=request // 添加
在前端页面使用request,修改load方法。
load() { //请求分页查询数据 //fetch("http://localhost:8084/user/page?pageNum="+this.pageNum+"&pageSize="+this.pageSize+"").then(res=>res.json()).then(res=>{ //使用axios封装的request this.request.get("http://localhost:8084/user/page",{ params:{ pageNum: this.pageNum, pageSize: this.pageSize, username: this.username, nickname:this.nickname, address:this.address } }).then(res=>{ console.log(res) this.tableData=res.data this.total=res.total }) }
这里有几个地方需要说明:
(1)如果出现这种没有数据的情况。
打开“开发者工具”我们会发现,现在数据放到records以及total中,这里是一个对象,所以我们的表格数据和总条目数据需要修改取值方式。
后端接口是这样的:
后端代码及解析详见任务八。
我们在任务六中的接口是这样的:
所以
console.log(res); this.tableData=res.records; this.total=res.total;
(2)使用 params整合传值
这样让前端传值比较整齐。
params:{ pageNum: this.pageNum, pageSize: this.pageSize, username: this.username, nickname:this.nickname, address:this.address }
(1)搜索按钮添加一个@click="load"点击事件,调用load方法。
(2)添加一个重置按钮,并为这个按钮添加一个@click="reset"点击事件,调用reset方法。
代码为:
搜索 重置
reset方法的代码为:
reset(){ this.username=""; this.nickname=""; this.address=""; this.load(); }
运行项目,实现模糊查询。
增加数据需要打开用户信息编辑对话框,然后输入对象值,执行添加操作,实现数据记录增加。
在 中添加一个对话框。对话框使用elementUI组件Dialog 对话框中的“嵌套表单的 Dialog”。
对话框这段代码放在 中的位置没有关系,一般情况,为了增加可读性,新添加的代码我们放到最后修改相关属性,代码如下:
取 消 确 定
data添加dialogFormVisible和form,并将dialogFormVisible初始化为不可见。
data(){ return { tableData:[], total:0, pageNum:1, pageSize:2, username:"", nickname:"", address:"", dialogFormVisible:false, form:{} } },
“新增”按钮添加调用hanleAdd()方法。
新增
主要目的是打开“添加用户”对话框,代码如下。
hanleAdd(){ this.dialogFormVisible = true; this.form={};//如果之前有填过值,可以置空 }
确 定
实现用户信息添加,代码如下。
insert(){ this.request.post("http://localhost:8084/user",this.form).then(res=>{ if(res){ this.$message.success("保存成功"); this.dialogFormVisible=false; this.load(); }else{ this.$message.error("保存失败"); } }) },
点击“新增”按钮,打开“用户信息”对话框。
添加用户信息,点击“确定”按钮,显示“保存成功”。
可以看到最后的数据已经添加。
数据表中的数据已经完成
这里有一个思考: 为什么密码那列为空!!!
这是因为,一般情况,系统会根据客户需求初始化一个通用密码,然后对密码进行MD5加密;
详细讲解为:
密码的安全问题:密码简单,明文密码
密码:1234 -------》 数据库:1234
这种方式一般安全性太低。
故要对密码进行加密,一般采用MD5加密,具体方法为:
MD5加密:1234+字符串(盐) 加密后生成32位的密码存到数据库中
登录的时候,对于密码则要进行解密,当原文(原密码)与盐一致,密文一致,才允许下一步操作。
MD5加密一般都需要在前端进行第一次加密,这样为了防止传递的是明文密码,然后再在后端进行二次加密。
以下方法仅供参考。
MD5加密,需要在用户表中再加一个salt字段,存放盐值。
注册时:
后端加密的方法
String salt = UUID.randomUUID().toString(); String password = user.getUserPassword();//取到前端传递的密码初始值 user.setUserPassword(getMD5Pwd(password, salt)).setUserSalt(salt);//对初始密码加盐,并存放盐值,然后继续后续操作即可
加密的方法getMD5Pwd 代码为:
/** * 封装一个方法 对密码进行加密 */ private String getMD5Pwd(String password, String salt) { String md5Pwd = password + salt; return DigestUtils.md5DigestAsHex(md5Pwd.getBytes()); }
登录时:
........ User selectUser = getUser("user_email", userEmail); if (selectUser == null) { return Result.error(405, "该邮箱不存在"); } String userSalt = selectUser.getUserSalt(); String userPassword = selectUser.getUserPassword(); if (userPassword.equals(getMD5Pwd(user.getUserPassword(), userSalt))) {//解密,并与盐值做比较 ........
为了项目连续性,这里就暂时不修改sys_user数据表结构,与本项目相关的MD5注册与登录,见专门撰写的博客。
因为前期增加用户信息已经基本搭好框架,我们在此基础上进行稍微完善就可以了,编辑用户信息比较简单。
编辑
添加handleEdit()方法,代码如下:
handleEdit(row){ console.log(row); this.form=row;//把当前行的数据赋值给form this.dialogFormVisible=true; }
运行项目,点击“编辑”可以打开“用户信息”对话框,实现数据更新,修改信息,因为后台调用的是saveOrUpdate(user)所以,mybatis会自动判断,然后实现更新。
数据表中的记录:
删除
添加handleDelete()方法,代码如下:
handleDelete(id){ this.request.delete("http://localhost:8084/user/"+id+"").then(res=>{ if(res){ this.$message.success("删除成功"); this.load(); }else{ this.$message.error("删除失败"); } }) },
选中一条记录,点击"删除"。
提示删除成功。
数据表中已删除相关记录。
此时会发现没有提示,直接删除数据,既不合理,对数据的安全性也没有保障。一般对“删除”按钮添加提示功能。
使用elementUI组件中的Popconfirm 气泡确认框,升级“删除”按钮如下。需要将原来在button中的handleDelete(scope.row.id)方法放到确认框中。
删除
(1)首先为表格添加可以多选的复选按钮,使用elementUI的table组件中的多选。
(2)添加了复选框列。
(3)为表格添加@selection-change="handleSelectionChange"事件。
编辑 删除
(4)运行
运行结果是这样的:
编写handleSelectionChange()方法,代码如下:
handleSelectionChange(val){ console.log(val); this.multipleSelection =val; },
在后端UserController类添加一个批量删除接口deleteBatch:
//使用mybtis-plus实现批量删除 @PostMapping("/del/batch/") public boolean deleteBatch(@RequestBody Listids){ return userService.removeByIds(ids); }
批量删除
编写delBatch方法。
注意: 传递IDS批量数据时,使用post请求。
delBatch(){ let ids=this.multipleSelection.map(v=>v.id);//map这个方法可以实现将multipleSelection中的对象扁平化处理。 console.log(ids); this.request.post("http://localhost:8084/user/del/batch/",ids).then(res=>{ if(res){ this.$message.success("批量删除成功"); this.load(); }else{ this.$message.error("批量删除失败"); } }) },
同时选中多条记录,实现批量删除。
特别说明: 可以参考前面删除按钮,添加一个警告弹窗。
本次任务,主要完成并掌握以下内容:
(1)掌握前端axios前后端跨域数据连接的方法;
(2)熟练引用Element的各类组件
在整个增删改查的过程中,我们发现一直要与后端的这个服务地址交互。每次写很麻烦,而且容易做错,这时候request.js的baseURL设置就有用了。
我们修改axios.create,代码如下:
const request = axios.create({ baseURL: 'http://localhost:8084', timeout: 5000 })
页面中做如下修改:
以后都可以不用写服务器地址啦!!!
今天是农历兔年春节,祝大家一切顺意!!!