Vue前後端交互
六、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獲取處理結果。
var p = new Promise(function(resolve,reject){
//成功時調用resolve()
//失敗時調用reject()
});
p.then(function(ret){
//從resolve得到正常結果
},function(ret){
//從reject得到錯誤信息
});
then參數中的函數返回值
- 返回Promise實例對象
返回該實例對象用於調用下一個then
p.then(function(ret){
return new Promise(...)
}).then(...)
- 返回普通值
返回的普通值會直接傳遞給下一個then,通過then函數中函數的參數接收該值(底層會對返回的普通值封裝爲一個Promise使得能夠繼續調用then)
p.then(function(ret){
return '莫逸風';
}).then(function(ret){
alert(ret); //莫逸風
})
基於Promise處理多個Ajax請求demo
<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))
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
<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
<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基本用法
語法結構
fetch(url).then(fn2)
.then(fn3)
...
.cach(fn)
基本用法
fetch('/abc').then(data=>{
return data.text();
}).then(ret=>{
//這裏得到的纔是最終的數據
console.log(ret);
})
demo
<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請求方式的參數傳遞
常規
<script>
fetch('http://localhost:8088/sayHi?name="莫逸風',{
method:'get'
}).then(function (data) {
return data.text();
}).then(function (data) {
alert(data);
});
</script>
restful形式
- post請求方式的參數傳遞
參數form表單形式
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表單形式
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)一樣
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基本用法
//去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傳遞參數
axios.get('http://localhost:8088/sayhi?name=莫逸風').then(function (ret) {
alert(ret.data)
})
restful風格接口
通過params選項傳遞參數
axios.get('http://localhost:8088/sayhi',{
params:{
name:"莫逸風"
}
}).then(function (ret) {
//data屬性是固定的用法,用於獲取後臺的實際數據
alert(ret.data)
})
- POST傳遞參數
通過對象傳遞參數(默認傳遞的是json格式的數據)
axios.post('http://localhost:8088/login',{
name:"莫逸風",
pass:"1234",
}).then(function (ret) {
//data屬性是固定的用法,用於獲取後臺的實際數據
alert(ret.data)
})
通過URLSearchParams傳遞參數(application/x-www-form-urlencoded)
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:響應狀態信息
axios.post('http://localhost:8088/login',param).then(function(ret){
console.log(ret);//所有數據都包含在此對象中
//對於json形式的響應數據可以直接獲取,不需要轉換
alert(ret.data.name);
})
- axios的全局配置
axios.defaults.timeout = 3000; //超時時間
//默認地址,再寫請求的時候只需要寫後面的路由就行了
axios.defaults.baseURL = 'http://localhost:3000/app';
axios.defaults.headers['mytoken']='aqwerwqwerqwer2ewrwe23eresdff23'//設置請求頭
demo
//配置請求的基準URL地址
axios.defaults.baseURL = 'http://localhost:8088/';
axios.get('sayhi?name=莫逸風').then(function (ret) {
//data屬性是固定的用法,用於獲取後臺的實際數據
alert(ret.data)
})
//注意,添加請求頭跨域需要後端設置AllowedHeader
//修改請求頭
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
- axios攔截器
請求攔截器
在請求發出之前設置一些信息
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)
})
響應攔截器(攔截器放到請求之上)
在獲取數據之前對數據做一些加工處理
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對象
<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來保證順序。
<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>