Vue的Ajax请求
axios简介
- Axios,是Web数据交互方式,是一个基于promise [5]的网络请求库,作用于node.js和浏览器中,它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生node.js http模块, 而在客户端 (浏览端) 则使用XMLHttpRequest。 [2]
- axios :不是vue的插件,可以在任何地方使用,推荐
axios的使用方式
1、使用npm安装
npm install axios
2、使用cdn链接axios
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
axios的语法
axios({// 请求方式method: 'post',url: 'api',// 传递参数data: obj,// 设置请求头信息headers: {key: value},responseType: 'json'
}).then(response => {// 请求成功let res = response.data;console.log(res);
}).catch(error => {// 请求失败,console.log(error);
});
axios案例
1、数据准备
- Student.json
[{"sid":1,"name":"mary","age":18,"gender":"女"},{"sid":2,"name":"lucy","age":18,"gender":"女"},{"sid":3,"name":"tom","age":19,"gender":"男"},{"sid":4,"name":"jack","age":18,"gender":"男"}
]
2、初使用问题
- VScode
- 解决办法
3、axios 发送get请求
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="js/vue.global.js"></script><script src="js/axios.min.js"></script>
</head>
<body><div id="app"><table cellspacing="0" cellpadding="0" border="1" width="500" align="center"><tr><th>学号</th><th>姓名</th><th>年龄</th><th>性别</th></tr><tr v-for="stu in stus"><td>{{stu.sid}}</td><td>{{stu.name}}</td><td>{{stu.age}}</td><td>{{stu.gender}}</td></tr></table></div><script>const vueApp = Vue.createApp({data:function(){return {stus:""}},created:function(){//发送ajax请求,将得到的数据赋值给stusaxios({method:"get",url:"json/students.json"}).then(resp => {this.stus = resp.data;});}});vueApp.mount("#app");</script>
</body>
</html>
- 或者
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="js/vue.global.js"></script><script src="js/axios.min.js"></script>
</head>
<body><div id="app"><table cellspacing="0" cellpadding="0" border="1" width="500" align="center"><tr><th>学号</th><th>姓名</th><th>年龄</th><th>性别</th></tr><tr v-for="stu in stus"><td>{{stu.sid}}</td><td>{{stu.name}}</td><td>{{stu.age}}</td><td>{{stu.gender}}</td></tr></table></div><script>const vueApp = Vue.createApp({data:function(){return {stus:""}},created:function(){//发送ajax请求,将得到的数据赋值给stusaxios.get("json/students.json").then(resp => {this.stus = resp.data;});}});vueApp.mount("#app");</script>
</body>
</html>
4、axios 发送post请求
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="js/vue.global.js"></script><script src="js/axios.min.js"></script>
</head>
<body><div id="app"><table cellspacing="0" cellpadding="0" border="1" width="500" align="center"><tr><th>学号</th><th>姓名</th><th>年龄</th><th>性别</th></tr><tr v-for="stu in stus"><td>{{stu.sid}}</td><td>{{stu.name}}</td><td>{{stu.age}}</td><td>{{stu.gender}}</td></tr></table></div><script>const vueApp = Vue.createApp({data:function(){return {stus:""}},created:function(){//发送ajax请求,将得到的数据赋值给stusaxios({method:"post",url:"json/students.json"}).then(resp => {this.stus = resp.data;});}});vueApp.mount("#app");</script>
</body>
</html>
- 注意:绝大多数web服务器,都不允许静态文件响应POST请求,所以这里运行会报错哦。
5、补充
- 为所有支持的请求方法提供了别名
- axios.request(confifig)
- axios.get(url[, confifig])
- axios.delete(url[, confifig])
- axios.head(url[, confifig])
- axios.post(url[, data[, confifig]])
- axios.put(url[, data[, confifig]])
- axios.patch(url[, data[, confifig]])
请求后台数据
1.index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="js/vue.global.js"></script><script src="js/axios.min.js"></script>
</head>
<body><div id="app"><table cellspacing="0" cellpadding="0" border="1" width="500" align="center"><tr><th>学号</th><th>姓名</th><th>年龄</th><th>性别</th><th>邮箱</th></tr><tr v-for="stu in stus"><td>{{stu.sid}}</td><td>{{stu.sname}}</td><td>{{stu.sage}}</td><td>{{stu.sgender}}</td><td>{{stu.semail}}</td></tr></table></div><script>const vueApp = Vue.createApp({data:function(){return {stus:""}},created:function(){//发送ajax请求,将得到的数据赋值给stusaxios.get("http://localhost:8888/day10_war_exploded/studentServlet?flag=getAllStudents").then(resp => {this.stus = resp.data;});}});vueApp.mount("#app");</script>
</body>
</html>
2.StudentServlet.java
package com.etime.servlet;import com.etime.entity.Student;
import com.fasterxml.jackson.databind.ObjectMapper;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;@WebServlet("/studentServlet")
public class StudentServlet extends BaseServlet {protected void getAllStudents(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {List<Student> list = new ArrayList<>();Student student1 = new Student(1,"范冰冰","女",18,"fbb@qq.com");Student student2 = new Student(2,"刘德华","男",18,"ldh@qq.com");Student student3 = new Student(3,"孙红雷","男",18,"shl@qq.com");list.add(student1);list.add(student2);list.add(student3);ObjectMapper mapper = new ObjectMapper();String res = mapper.writeValueAsString(list);PrintWriter out = resp.getWriter();out.print(res);out.close();}
}
3.跨域问题
-
指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
-
同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域,在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
-
跨域问题怎么出现的?
- 开发一些前后端分离的项目,比如使用 Servlet + Vue 开发时,后台代码在一台服务器上启动,前台代码在另外一台电脑上启动,此时就会出现问题。
- 比如:
- 后台 地址为http://localhost:8080/
- 前台 地址为 http://127.0.0.1:5500/
- 此时端口号不一致, 不符合同源策略,造成跨域问题。
-
CorsFilter
package com.etime.filter;import org.apache.commons.lang.StringUtils;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*跨域请求*/
@WebFilter("/*")
public class CorsFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletResponse response = (HttpServletResponse) servletResponse;HttpServletRequest request = (HttpServletRequest) servletRequest;request.setCharacterEncoding("utf-8");// 不使用*,自动适配跨域域名,避免携带Cookie时失效String origin = request.getHeader("Origin");if(StringUtils.isNotBlank(origin)) {response.setHeader("Access-Control-Allow-Origin", origin);}// 自适应所有自定义头String headers = request.getHeader("Access-Control-Request-Headers");if(StringUtils.isNotBlank(headers)) {response.setHeader("Access-Control-Allow-Headers", headers);response.setHeader("Access-Control-Expose-Headers", headers);}// 允许跨域的请求方法类型response.setHeader("Access-Control-Allow-Methods", "*");// 预检命令(OPTIONS)缓存时间,单位:秒response.setHeader("Access-Control-Max-Age", "3600");// 明确许可客户端发送Cookie,不允许删除字段即可response.setHeader("Access-Control-Allow-Credentials", "true");filterChain.doFilter(request, response);}@Overridepublic void destroy() {}
}
综合练习
1.register.html–注册功能
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>注册</title><script src="js/vue.global.js"></script><script src="js/axios.min.js"></script>
</head>
<body><div id="app"><form>账号:<input type="text" v-model="username" @blur="checkUsername()"><span style="color:red">{{username_msg}}</span><br>密码:<input type="password" v-model="pwd" @blur="checkPwd()"><span style="color:red">{{pwd_msg}}</span><br><input type="button" value="注册" @click="register()"></form></div><script>const vueApp = Vue.createApp({data:function(){return {username:"",pwd:"",username_msg:"",pwd_msg:"",username_flag:false,pwd_flag:false}},methods:{checkUsername:function(){if (this.username == "") {this.username_msg = "账号不能为空";this.username_flag = false;} else if (this.username.length < 6) {this.username_msg = "账号至少6个字符";this.username_flag = false;} else {//账号是否为已注册账号的判断axios({method:"get",url:"http://localhost:8888/day10_war_exploded/managerServlet?flag=checkUsername&username="+this.username}).then(resp => {if (resp.data) {this.username_msg = "";this.username_flag = true;} else {this.username_msg = "账号已存在";this.username_flag = false;}});}},checkPwd:function(){if (this.pwd == "") {this.pwd_msg = "密码不能为空";this.pwd_flag = false;} else if (this.pwd.length < 8) {this.pwd_msg = "密码至少8个字符";this.pwd_flag = false;} else {this.pwd_msg = "";this.pwd_flag = true;}},register:function(){if (this.username_flag && this.pwd_flag) {//处理需要传递给后端的数据,使用这种方式处理数据时,method值必须是postlet params = new URLSearchParams();params.append("flag","register");params.append("username",this.username);params.append("pwd",this.pwd);//数据全部通过校验axios({method:"post",url:"http://localhost:8888/day10_war_exploded/managerServlet",data:params}).then(resp => {if (resp.data) {alert("注册成功");window.location.href = "login.html";} else {alert("注册失败,请稍后再试");}});} else {alert("请认真填写数据");}}}});vueApp.mount("#app");</script>
</body>
</html>
2.login.html-登录功能
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>登录</title><script src="js/vue.global.js"></script><script src="js/axios.min.js"></script>
</head>
<body><div id="app"><form>账号:<input type="text" v-model="username" @blur="checkUsername()"><span style="color:red">{{username_msg}}</span><br>密码:<input type="password" v-model="pwd" @blur="checkPwd()"><span style="color:red">{{pwd_msg}}</span><br><input type="button" value="登录" @click="login()"></form></div><script>const vueApp = Vue.createApp({data(){return {username:"",pwd:"",username_msg:"",pwd_msg:"",username_flag:false,pwd_flag:false}},methods:{checkUsername(){if (this.username == "") {this.username_msg = "账号不能为空";this.username_flag = false;} else if (this.username.length < 6) {this.username_msg = "账号至少6个字符";this.username_flag = false;} else {axios({method:"get",url:"http://localhost:8888/day10_war_exploded/managerServlet?flag=checkUsername&username="+this.username}).then(resp => {if (resp.data) {this.username_msg = "该账号未注册,请先注册";this.username_flag = false;} else {this.username_msg = "";this.username_flag = true;}});}},checkPwd(){if (this.pwd == "") {this.pwd_msg = "密码不能为空";this.pwd_flag = false;} else if (this.pwd.length < 8) {this.pwd_msg = "密码至少8个字符";this.pwd_flag = false;} else {this.pwd_msg = "";this.pwd_flag = true;}},login(){if (this.username_flag && this.pwd_flag) {let params = new URLSearchParams();params.append("flag","login");params.append("username",this.username);params.append("pwd",this.pwd);axios({method:"post",url:"http://localhost:8888/day10_war_exploded/managerServlet",data:params}).then(resp => {if (resp.data) {alert("登录成功");window.location.href = "index.html";} else {alert("密码有误,请查证后再登录");}});} else {alert("请认真填写数据");}}}});vueApp.mount("#app");</script>
</body>
</html>
3.学生信息展示
(1) studentInfo.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="js/vue.global.js"></script><script src="js/axios.min.js"></script>
</head>
<body><div id="app"><table cellspacing="0" cellpadding="0" border="1" width="500" align="center"><tr><th>学号</th><th>姓名</th><th>年龄</th><th>性别</th><th>邮箱</th><th>头像</th></tr><tr v-for="stu in stus"><td>{{stu.sid}}</td><td>{{stu.sname}}</td><td>{{stu.sage}}</td><td>{{stu.sgender}}</td><td>{{stu.semail}}</td><td><img :src="'http://localhost:8888/sms_pic/student/'+stu.sphoto" width="50"></td></tr></table><div><a href="javascript:void(0)" @click="getStudentByPage(1)">首页</a><a href="javascript:void(0)" @click="getStudentByPage(prevPage)">上一页</a>{{page}}/{{countPages}}<a href="javascript:void(0)" @click="getStudentByPage(nextPage)">下一页</a><a href="javascript:void(0)" @click="getStudentByPage(countPages)">尾页</a></div></div><script>const vueApp = Vue.createApp({data:function(){return {stus:"",page:"",countPages:"",prevPage:"",nextPage:""}},methods:{getStudentByPage(p){let params = new URLSearchParams();params.append("flag","getStudentByPage");params.append("page",p);axios({method:"post",url:"http://localhost:8888/day10_war_exploded/studentServlet",data:params}).then(resp => {this.stus = resp.data.list;this.page = resp.data.page;this.countPages = resp.data.countPages;this.prevPage = resp.data.prevPage;this.nextPage = resp.data.nextPage;});}},created:function(){this.getStudentByPage(1);}});vueApp.mount("#app");</script>
</body>
</html>
(2) PageUtil.java-分页代码
package com.etime.util;import java.util.List;public class PageUtil {private int page; //当前页页码private int rows; //每页显示条数private int index; //偏移量private int countRows; //总条数private int countPages; //总页数private int prevPage; //当前页的上一页页码private int nextPage; //当前页的下一页页码private List list; //当前页的数据public PageUtil(String page,int rows,int countRows){init_page(page);this.rows = rows;init_index();this.countRows = countRows;init_countPages();init_prevPage();init_nextPage();}private void init_page(String page){if (page == null || "".equals(page)) {this.page = 1;} else {this.page = Integer.parseInt(page);}}private void init_index(){this.index = (this.page - 1) * this.rows;}private void init_countPages(){int mod = this.countRows % this.rows;if (mod == 0) {this.countPages = this.countRows / this.rows;} else {this.countPages = this.countRows / this.rows + 1;}}private void init_prevPage(){if (this.page == 1) {this.prevPage = 1;} else {this.prevPage = this.page - 1;}}private void init_nextPage(){if (this.page == this.countPages) {this.nextPage = this.countPages;} else {this.nextPage = this.page + 1;}}public int getPage() {return page;}public int getRows() {return rows;}public int getIndex() {return index;}public int getCountRows() {return countRows;}public int getCountPages() {return countPages;}public int getPrevPage() {return prevPage;}public int getNextPage() {return nextPage;}public List getList() {return list;}public void setList(List list) {this.list = list;}
}
(3)StudentServlet.java
protected void getStudentByPage(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {//分页数据查询String page = req.getParameter("page");int rows = 10;int countRows = studentService.getCountRows();PageUtil pageUtil = new PageUtil(page, rows, countRows);List<Student> list = studentService.getStudentByPage(pageUtil);pageUtil.setList(list);ObjectMapper mapper = new ObjectMapper();String res = mapper.writeValueAsString(pageUtil);PrintWriter out = resp.getWriter();out.print(res);out.close();}
(3)StudentServlet.java
protected void getStudentByPage(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {//分页数据查询String page = req.getParameter("page");int rows = 10;int countRows = studentService.getCountRows();PageUtil pageUtil = new PageUtil(page, rows, countRows);List<Student> list = studentService.getStudentByPage(pageUtil);pageUtil.setList(list);ObjectMapper mapper = new ObjectMapper();String res = mapper.writeValueAsString(pageUtil);PrintWriter out = resp.getWriter();out.print(res);out.close();}