Ajax
即“Asynchronous Javascript And XML”(異步 JavaScript 和 XML),是指一種創建交互式網頁應用的網頁開發技術。Ajax的產生主要是因爲在沒有異步請求的時候,網絡使用的都是同步請求,設想一下你在填寫銀行辦卡的業務表單,花費了十幾分鐘好不容易寫完了發送同步請求到服務器提交表單,但因爲同步請求的特性,在上傳以及服務器響應的過程中,你無法繼續你的其他業務操作,等了幾分鐘服務器響應給你的數據卻告訴你身份證號碼填寫錯誤需要重新提交,這種時候別提多奔潰了。於是乎Ajax就有了它誕生的意義了,它可以執行異步的請求,在你填寫表單的同時,數據便上傳到服務器驗證了,同時你可以繼續你填寫表單的動作,當服務器響應回數據時立馬在表單的input框標紅告訴你填寫錯誤,你可以很快的更改錯誤的數據不需要等待服務器的響應。
ES5中的Ajax
在ECMAScript 5中,Ajax是依託XMLHttpRequest()實例對象來實現的,支持IE7+, Firefox, Chrome, Opera, Safari等瀏覽器,由於現在市面上大部分計算機瀏覽器都在IE8+以上,所以暫不講述低版本IE的Ajax使用了,具體方法可自行百度 ActiveXObject()對象的使用。
首先建立實例
if(typeof window.XMLHttpRequest())
let xhr=new XMLHttpReques();
else{
throw new Error("NO XHR object available");//判斷下兼容性
}
接下來就可以開始發送Ajax請求了,主要使用XMLHttpRequest()對象的open()、send()來個方法。
xhr.open(method,url,async);
xhr.send();
其中method中有兩個方法‘GET’和‘POST’,兩個方法中POST更加穩定且具有保密性,適合較大的數據和像密碼一類需要保密的數據,而GET方法回顯示在url中,以?分隔開地址,&分隔不同數據。如
上圖中 type=codecamp,order=hot,paytype=all分別是三組通過GET方法傳輸到服務器的數據。
接下來如何獲取服務器響應的數據呢?
以下是一個實例:
xhr.onreadyStatechange = function(){
if(xhr.readyState == 4){
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
alert(xhr.responseText);
}else{
alert("Request was unsuccessful:" + xhr.status );
}
}
};
我們看下onreadyStatechange 事件w3c的解釋
這樣就很明確了,當readyState===4且statu狀態爲200-299區間時,就說明數據就成功響應了。通過responseText屬性就可以獲取響應數據的字符串形式了。具體的http狀態碼也可自行百度。
自此就完成了ES5中Ajax請求。
ES6中的Ajax請求
如果你經常是用jquery中的ajax,那你可能感受過回調地獄(callback hell)的恐懼,如果用的還是原生ajax,那可能難上加難了。而ES6中的Promise對象卻很好的解決了這個問題。由於筆者剛學的ES6,對ES6的使用還不是很熟練,如果有錯誤的地方,還請多多包涵並告知。
首先,找過jquery使用ajax異步請求的回調例子。
$.ajax({
url: url1,
success: function(data){
$.ajax({
url: url2,
success: function(data){
$.ajax({
//...
});
}
});
}
});
如上所示,下層請求依賴於上層的請求,如果請求的階數多了,那代碼將顯得十分的臃腫,可讀性也很差。
而在ES6中,上述代碼的實現如下:
異步請求
let http = function(url){
return new Promise((resolve,reject)=>{
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = ()=>{
if(xhr.readyState ==4 && xhr.status==200){
resolve(xhr.responseText);
}
};
xhr.open("GET",url);
xhr.send();
});
};
let exp1 = http("www.baidu.com");
exp1.then(res=>{
console.log(res);
return http('www.taobao.com');
}).then(res=>{
alert(res);
console.info(res);
})
一次性完成所有請求
let first = new Promise ((resolve,reject)=>{
$.ajax({
url:url1,
success:data=>{
if(data.Status=="success"){
resolve(data.ResultJson)//在異步操作成功時調用
}else{
reject(data.ErrMsg);//在異步操作失敗時調用
}
}
})
})
let second = new Promise((resolve,reject)=>{
$ajax({
url:url2,
success: data=>{
if(...){
resolve(....)
}else{
reject(...);
}
}
})}
Promise.all([first,second]).then(([ResultJson1,ResultJson2])=>{
//這裏寫等這兩個ajax都成功返回數據才執行的業務邏輯
})
另外還有async函數解決異步請求的方案,從語義上和語法上更優,可維護性更強。
let http = function(url){
return new Promise((resolve,reject)=>{
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = ()=>{
if(xhr.readyState ==4 && xhr.status==200){
resolve(xhr.responseText);
}
};
xhr.open("GET",url);
xhr.send();
});
};
async function func(name){
const name2 = await http(name);
console.log(name2);
const name3 = await http('taobao.com');
console.log(name3);
return http('www.hao123.com');
}
func('www.baidu.com').then(res=>{
console.log(res);
});
這樣子寫代碼是不是清晰明瞭很多。
Vue.js框架中的Ajax
從學習前端到現在幾乎都在使用Vue框架學習,所以這裏怎麼可能少了vue中如何使用Ajax請求呢?
首先Vue框架中不想JQuery那樣封裝了自己的ajax請求方法,Vue官方推薦使用axios插件,這是一個Http庫,容易使用功能強大,且更加符合Vue的MVVM設計概念。
axios的特點如下:
1.從瀏覽器中創建 XMLHttpRequest
2.從 node.js 發出 http 請求
3.支持 Promise API
4.攔截請求和響應
5.轉換請求和響應數據
6.取消請求
7.自動轉換JSON數據
8.客戶端支持防止CSRF/XSRF
(本小白剛開始使用,很多特性暫時還沒有接觸到)
由於從node.js發出的http請求,所以可以在node服務端設置代理服務器可以很好的解決跨域問題,支持Promise也更加的適應了ES6的潮流。
關於使用方法:
首先當然是安裝(執行命令行)
npm i axios
//或者使用cdn:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
在項目中的main.js中引用包,並付給Vue原型屬性覆蓋,從而修改原型鏈
import axios from 'axios'
Vue.prototype.$axios = axios
使用方法
//默認使用GET方法,可自行配置
this.$axios( 'www.baidu.com').then(res => {
console.log(res);
}
})
.catch(error => {
alert(error);
});
//POST方法
this.$axios.post( 'www.baidu.com',{username:“abc”,password:xxx}).then(res => {
console.log(res);
}
})
.catch(error => {
alert(error);
});
設置跨域代理服務器
在vue-cli3.0中可以很容易的設置代理服務器,先打開配置文件vue.config.js添加配置proxy(代理)
// const path = require('path');
// function resolve(dir) {
// return path.join(__dirname,dir)
// }
module.exports = {
devServer:{
proxy: {
'/api': {
target: 'http://www.baidu.com', //代理服務器請求的目標服務器地址
changeOrigin: true, //是否跨域
ws: true,
pathRewrite: {
'^/api': '' //用api代替目標服務器地址,在請求時重寫
}
}
}
},
baseUrl: "./"
};
之後需要跨域訪問就更改請求操作,代碼如下
this.$axios( 'api/index.php?id=0').then(res => { //這裏用api替換了原本的服務器地址
console.log(res);
}
})
.catch(error => {
alert(error);
});