轻松入门vue系列
Vue前后端交互
- 六、Vue前后端交互
- 1. 前后端交互模式
- 2. Promise的相关概念和用法
- Promise基本用法
- then参数中的函数返回值
- 基于Promise处理多个Ajax请求demo
- Promise常用API
- 3. fetch进行接口调用
- fetch基本用法
- fetch请求参数
- fetch响应结果
- 4. axios进行接口调用
- axios基本用法
- axios的常用API(参数传递)
- 5. asyns/await接口调用
- async/await的基本用法
- 多个异步请求的场景
六、Vue前后端交互
项目中一般结合async/await语法使用axios调用接口
1. 前后端交互模式
1. 接口调用方式
原生ajax、基于jQuery的ajax、fetch、axios
2. 传统的URL
格式:schema://host:port/path?query#fragment
- schema:协议,例如http、https、ftp等。
- host:域名或者IP地址。
- port:端口,http默认端口80,可以省略。
- path:路径,例如/abc/a/b/c
- query:查询参数,例如uname=lisi&age=12
- fragment:锚点(哈希Hash),用于定位页面的某个位置
3. Restful形式的URL
HTTP请求方式
- GET 查询
- POST 添加
- PUT 修改
- DELETE 删除
2. Promise的相关概念和用法
JS中常见的异步调用:定时任务、ajax、事件函数
Promise是异步编程的一种解决方案,从语法上讲,Promise是一个对象,从它可以获取异步操作的消息。
使用Promise主要有以下好处:
- 可以避免多层异步调用嵌套问题(回调地狱)
- Promise对象提供了简介的API,使得控制异步操作更加容易
Promise基本用法
-
实例化Promise对象,构造函数中传递函数,该函数中用于处理异步任务。
-
resolve和reject两个(方法)参数用于处理成功和失败两种情况,并通过p.then获取处理结果。
1 2 3 4 5 6 7 8 9 | var p = new Promise(function(resolve,reject){ //成功时调用resolve() //失败时调用reject() }); p.then(function(ret){ //从resolve得到正常结果 },function(ret){ //从reject得到错误信息 }); |
then参数中的函数返回值
- 返回Promise实例对象
返回该实例对象用于调用下一个then
1 2 3 | p.then(function(ret){ return new Promise(...) }).then(...) |
- 返回普通值
返回的普通值会直接传递给下一个then,通过then函数中函数的参数接收该值(底层会对返回的普通值封装为一个Promise使得能够继续调用then)
1 2 3 4 5 | p.then(function(ret){ return '莫逸风'; }).then(function(ret){ alert(ret); //莫逸风 }) |
基于Promise处理多个Ajax请求demo
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 | <script> //Promise基本使用,原生ajax function getText(url) { var p = new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { //readyState表示文档状态 if (xhr.readyState != 4) return; if (xhr.readyState == 4 && xhr.status == 200){ //处理正常情况 resolve(xhr.responseText); }else { reject('服务器错误'); } }; xhr.open('get',url); xhr.send(null); }); return p; } //链式调用解决回调地狱,return一个新的调用就可以继续调用新的then()了。 getText('http://localhost:8088/saymo').then( function (data) { alert(data); return getText('http://localhost:8088/sayyi'); },function (info) { alert(info); } ).then( function (data) { alert(data); return getText('http://localhost:8088/sayfeng') } ).then( function (data) { alert(data); } ); </script> |
上方调用方式会调用后端,产生跨域问题(解决方案回头仔细研究,先放一段代码(SpringBoot))
跨域解决方案参考
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 | 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 public class CorsConfig { public CorsConfig(){ } @Bean public CorsFilter corsFilter(){ //1.添加cors配置信息 CorsConfiguration config = new CorsConfiguration(); config.addAllowedOrigin("http://localhost:63343"); //设置是否发送cookie信息 config.setAllowCredentials(true); //设置允许请求的方式 config.addAllowedMethod("*"); //设置允许的header config.addAllowedHeader("*"); //2.为url添加映射路径 UrlBasedCorsConfigurationSource corsSource = new UrlBasedCorsConfigurationSource(); corsSource.registerCorsConfiguration("/**",config); //3.返回从新定义好的corsSource return new CorsFilter(corsSource); } } |
Promise常用API
- 实例方法
p.then() //得到异步任务的处理结果
p.catch() //获取异常信息
p.finally() //成功与否都会执行(尚且不是正式标准)
demo
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 | <script> function foo() { return new Promise(function (resolve, reject) { setTimeout(function () { //resolve(123)//正常情况 reject("出错了");//错误情况 },1000) }) } foo().then(function (data) { alert(data); }).catch(function (data) { alert(data); }).finally(function () { alert("结束了") }) //与上面效果相同 foo().then(function (data) { alert(data); },function (data) { alert(data); }).finally(function () { alert("结束了") }) </script> |
- 对象方法
Promise.all()并发处理多个异步任务,所有任务都执行完成才能得到结果
Promise.race()并发处理多个异步任务,只要有一个任务完成就能得到结果
demo
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 | <script> function getText(url) { var p = new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { //readyState表示文档状态 if (xhr.readyState != 4) return; if (xhr.readyState == 4 && xhr.status == 200){ //处理正常情况 resolve(xhr.responseText); }else { reject('服务器错误'); } }; xhr.open('get',url); xhr.send(null); }); return p; } var p1 = getText("http://localhost:8088/saymo"); var p2 = getText("http://localhost:8088/sayyi"); var p3 = getText("http://localhost:8088/sayfeng"); //result是一个数组形式的三个数据,顺序和p1,p2,p3顺序相同 Promise.all([p1,p2,p3]).then(function (result) { alert(result); }) //result返回一个数据,最快返回的一个 Promise.race([p1,p2,p3]).then(function (result) { alert(result); }) </script> |
3. fetch进行接口调用
更加简单的数据获取方式,功能更强大、更灵活,可以看做是xhr的升级版
基于Promise实现
fetch基本用法
语法结构
1 2 3 4 | fetch(url).then(fn2) .then(fn3) ... .cach(fn) |
基本用法
1 2 3 4 5 6 | fetch('/abc').then(data=>{ return data.text(); }).then(ret=>{ //这里得到的才是最终的数据 console.log(ret); }) |
demo
1 2 3 4 5 6 7 8 9 10 11 | <script type="application/javascript"> /** * Fetch API 基本用法 */ fetch('http://localhost:8088/saymo').then(function (data) { //text()方法属于fetchAPI的一部分,它返回一份Promise实例对象,用于获取后台返回的数据 return data.text(); }).then(function (data) { alert(data); }) </script> |
fetch请求参数
- 常用配置选项
method(String):HTTP请求方法,默认为GET(GET、POST、PUT、DELETE)
body(String):HTTP的请求参数
headers(Object):HTTP的请求头,默认为{}
- get请求方式的参数传递
常规
1 2 3 4 5 6 7 8 9 | <script> fetch('http://localhost:8088/sayHi?name="莫逸风',{ method:'get' }).then(function (data) { return data.text(); }).then(function (data) { alert(data); }); </script> |
restful形式
1 |
- post请求方式的参数传递
参数form表单形式
1 2 3 4 5 6 7 8 9 10 11 | fetch('http://localhost:8088/login',{ method:'post', body:, headers:{ 'Content-Type':'application/x-www-form-urlencoded', } }).then(function (data) { return data.text(); }).then(function (data) { alert(data); }) |
参数json表单形式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | fetch('http://localhost:8088/login',{ method:'post', body:JSON.stringify({ name:'莫逸风', pass:'1234', }), headers:{ 'Content-Type':'application/json', } }).then(function (data) { return data.text(); }).then(function (data) { alert(data); }); |
fetch响应结果
text():将返回体处理成字符串类型
json():返回结果和JSON.parse(responseText)一样
1 2 3 4 5 6 7 | fetch('http://localhost:8088/sayhi?name=莫逸风',{ method:'get' }).then(function (data) { return data.json(); }).then(function (data) { alert(data); }); |
4. axios进行接口调用
axios(官网:https://github.com/axios/axios)是一个基于Promise用于浏览器和node.js的HTTP客户端
中文说明文档
它具有一下特征:
- 支持浏览器和node.js
- 支持promise
- 能拦截请求和相应
- 自动转换JSON数据
axios基本用法
1 2 3 4 5 6 7 8 | //去github下载文件,此js位于axios-master\dist <script src="axios.js"></script> <script> axios.get('http://localhost:8088/saymo').then(function (ret) { //data属性是固定的用法,用于获取后台的实际数据 alert(ret.data) }) </script> |
axios的常用API(参数传递)
- get:查询数据
- post:添加数据
- put:修改数据
- delete:删除数据
- get传递参数
通过URL传递参数
1 2 3 | axios.get('http://localhost:8088/sayhi?name=莫逸风').then(function (ret) { alert(ret.data) }) |
restful风格接口
1 |
通过params选项传递参数
1 2 3 4 5 6 7 8 | axios.get('http://localhost:8088/sayhi',{ params:{ name:"莫逸风" } }).then(function (ret) { //data属性是固定的用法,用于获取后台的实际数据 alert(ret.data) }) |
- POST传递参数
通过对象传递参数(默认传递的是json格式的数据)
1 2 3 4 5 6 7 | axios.post('http://localhost:8088/login',{ name:"莫逸风", pass:"1234", }).then(function (ret) { //data属性是固定的用法,用于获取后台的实际数据 alert(ret.data) }) |
通过URLSearchParams传递参数(application/x-www-form-urlencoded)
1 2 3 4 5 6 7 | var param = new URLSearchParams(); param.append('name','莫逸风'); param.append('pass','12345'); axios.post('http://localhost:8088/login',param).then(function (ret) { //data属性是固定的用法,用于获取后台的实际数据 alert(ret.data) }) |
- axios的响应结果
- data:实际响应回来的数据
- headers:响应头信息
- status:响应状态码
- statusText:响应状态信息
1 2 3 4 5 | axios.post('http://localhost:8088/login',param).then(function(ret){ console.log(ret);//所有数据都包含在此对象中 //对于json形式的响应数据可以直接获取,不需要转换 alert(ret.data.name); }) |
- axios的全局配置
1 2 3 4 | axios.defaults.timeout = 3000; //超时时间 //默认地址,再写请求的时候只需要写后面的路由就行了 axios.defaults.baseURL = 'http://localhost:3000/app'; axios.defaults.headers['mytoken']='aqwerwqwerqwer2ewrwe23eresdff23'//设置请求头 |
demo
1 2 3 4 5 6 | //配置请求的基准URL地址 axios.defaults.baseURL = 'http://localhost:8088/'; axios.get('sayhi?name=莫逸风').then(function (ret) { //data属性是固定的用法,用于获取后台的实际数据 alert(ret.data) }) |
1 2 3 | //注意,添加请求头跨域需要后端设置AllowedHeader //修改请求头 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; |
- axios拦截器
请求拦截器
在请求发出之前设置一些信息
1 2 3 4 5 6 7 8 9 10 11 12 | axios.interceptors.request.use(function (config) { config.baseURL = "http://localhost:8088/"; alert(config.url); return config; },function (err) { console.log(err); }) axios.get('sayhi?name=莫逸风').then(function (ret) { //data属性是固定的用法,用于获取后台的实际数据 alert(ret.data) }) |
响应拦截器(拦截器放到请求之上)
在获取数据之前对数据做一些加工处理
1 2 3 4 5 6 7 8 9 10 11 | axios.interceptors.response.use(function (res) { var data = res.data; return data; },function (err) { console.log(err); }) axios.get('sayhi?name=莫逸风').then(function (res) { //data属性是固定的用法,用于获取后台的实际数据 alert(res) }) |
5. asyns/await接口调用
async/await的基本用法
-
async/await是ES7引入的语法,可以更加方便的进行异步操作
-
async关键字用于函数上(async函数的返回值是Promise实例对象)
-
await关键字用于async函数中(await可以得到异步的结果)
await后跟一个Promise对象实现异步任务,async返回值是一个Promise对象
1 2 3 4 5 6 7 8 9 10 11 12 | <script src="axios.js"></script> <script> axios.defaults.baseURL = 'http://localhost:8088/'; async function queryData(){ var ret = await axios.get('saymo'); //alert(ret.data); return ret.data; } queryData().then(function (data) { alert(data); }); </script> |
多个异步请求的场景
不需要.then来保证顺序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <script> axios.defaults.baseURL = 'http://localhost:8088/'; async function queryData(){ var ret = await axios.get('saymo'); alert(ret.data); var ret1 = await axios.get('sayyi'); alert(ret1.data); var ret2 = await axios.get('sayfeng'); return ret2.data; } queryData().then(function (data) { alert(data); }); </script> |