一:Ajax基本概念
Ajax 的全稱是Asynchronous JavaScript and XML,其中,Asynchronous 是異步的意思,它有别于傳統web開發中采用的同步的方式。XML:extensiable markup language 被稱作可擴充标記語言。
簡要潔說ajax就是異步的
javascript
和
xml
,它是一種技術方案,但是不是一種技術,其核心就是浏覽器的XMLHttpRequest對象,ajax方案就是利用JavaScript操作XMLHttpRequest對象來讓浏覽器發出HTTP請求和響應,實作在頁面不重新整理的情況下和服務端資料進行互動。
XMLHttpRequest詳盡解析
Ajax由下列技術組合而成:
1.使用CSS和XHTML來表示。
2.使用DOM模型來互動和動态顯示。
3.使用XMLHttpRequest來和伺服器進行異步通信。
4.使用javascript來綁定和調用。
Ajax的主要作用及優點:
1.最大的一點是頁面無重新整理,在頁面内與伺服器通信,給使用者的體驗非常好。
2.使用異步方式與伺服器通信,不需要打斷使用者的操作,具有更加迅速的響應能力。
3.可以把以前一些伺服器負擔的工作轉嫁到用戶端,利用用戶端閑置的能力來處理,減輕伺服器和帶寬的負擔,節約空間和寬帶租用成本。并且減輕伺服器的負擔,ajax的原則是“按需取資料”,可以最大程度的減少備援請求,和響應對伺服器造成的負擔。
4.基于标準化的并被廣泛支援的技術,不需要下載下傳插件或者小程式。
二:利用Ajax和背景互動
上文多次提到了ajax的優點就是可以在頁面不重新整理的條件下與背景伺服器進行通信提升使用者的體驗,那麼下來我從最開始的前後端資料互動一直test到最後ajax;
01 form表單送出
<form action="/form.html" method="get">
<input type="text" name="username" placeholder="username">
<input type="password" name="password" placeholder="password" >
<input type="submit">
</form>
點選submit按鈕後我們頁面會重新整理或者說跳轉到新的頁面,之是以這樣就是url發生了改變假設域名本身為:
127.0.0.1:8080/form.html
新的url 為:
127.0.0.1/form.html?username=lay&password=12345
02 ajax
思路:
我們通過JavaScript操作浏覽器自帶的
XMLHttpRequest
對象來和後端進行資料互動,那麼該過程是異步的。我們将
HTTPrequest
發送後,執行下面的代碼,什麼時候監聽到資料傳回了我們再對資料進行操作。這樣就可以實作異步的資料互動。
02-1 :我們先試試同步的方式送出資料和擷取資料
var xhr = new XMLHttpRequest();
//ajax第一步 ,建立XMLHttpRequest對象,
xhr.open('GET','/hello.json',false)
// open(method, url [, async = true [, username = null [, password = null]]])
// method: 請求的方式,如GET/POST/HEADER等,這個參數不區分大小寫
// url: 請求的位址,可以是相對位址如example.php,
// 這個相對是相對于目前網頁的url路徑;也可以是絕對位址如http://www.example.com/example.php
// async: 預設值為true,即為異步請求,若async=false,則為同步請求
xhr.send();
//發送請求
var data = xhr.responseText;
//擷取傳回的資料
console.log(data);
http-server上測試結果:
我們可以看到資料正常輸出但是會報出一個警告翻譯過來就是:
主線程上的同步xmlhttpRequest由于其對最終使用者體驗的不利影響而被棄用。
解析:同步的請求方式假設我們發送或者請求的過程比較漫長,那麼因為其是同步的是在主線程上的,是以會影響其後的操作
02-2: 竟然同步不行那麼我們采用異步的方式
var xhr = new XMLHttpRequest();
xhr.open('GET','/hello.json',true);
xhr.send();
var data = xhr.responseText;
console.log(data);
結果:控制台沒有輸出data
解析:因為我們請求ajax是異步的是以說我們發送完資料後給data指派傳回的資料然後輸出。但是沒等到
responseText
傳回來,我們已經
console.log
它了是以自然會輸出空了。
于是
readystatechange
和
onload
來救場了
02-3: 使用document下的load事件來解決問題
var xhr = new XMLHttpRequest();
xhr.open('GET','/hello.json',true);
xhr.send();
xhr.addEventListener('load',function(){
var data = xhr.responseText;
console.log(data);
})
結果:正常擷取到了資料
02-4 使用readystatechange也可以實作相同的作用
var xhr = new XMLHttpRequest();
xhr.open('GET','/hello.json',true);
xhr.send();
xhr.addEventListener('readystatechange',function(){
if(xhr.readyState === 4 && xhr.status === 200) {
//readyState: 表示資料互動是否完畢, 4表示完成
//status :表示伺服器的狀态是否正常 200 -->300 && 304 表示成功
var data = xhr.responseText;
console.log(data);
}
})
那麼問題來了:onreadystatechange 和 onload都可以監聽到資料是否獲得,那麼二者有何差別呢?
02-5 : 簡單對比onreadystatechange 和 onload
var xhr = new XMLHttpRequest();
xhr.open('GET','/hello.json',true);
xhr.send();
console.log('readystatechange'+xhr.readyState);
xhr.onreadystatechange = function(){
console.log('readystatechange'+xhr.readyState);
}
xhr.onload = function() {
console.log(xhr.status);
if(xhr.status >= 200 && xhr.status<300 || xhr.status === 304) {
var data = xhr.responseText;
console.log(data);
}else {
console.log('error');
}
}
xhr.onerror= function() {
console.log('error');
}
結果:
解析:
我們可以看到readystatechange先于onload執行,load事件就想當于readState的值為4後觸發的事件,也就是資料互動完成後觸發onload,如果不需要跟蹤請求傳回之前的過程時,用load更加省事兒。
三:實戰ajax
經過上述的了解那麼我們就可以寫一個ajax出來
寫法一:
var xhr = new XMLHttpRequest()//
XMLHttpRequest 是一個函數通過new的方式生成一個對象
xhr.open('GET', 'http://api.jirengu.com/weather.php', true)
//open 設定參數 GRT 請求類型 'http://'請求位址 true 異步的方式
xhr.onreadystatechange = function(){
if(xhr.readyState === 4) {
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
//成功了
console.log(xhr.responseText)
} else {
console.log('伺服器異常')
}
}
}
xhr.onerror = function(){
console.log('伺服器異常')
}
xhr.send()//發送請求
寫法2:
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://api.jirengu.com/weather.php', true)
xhr.onload = function(){
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
//成功了
console.log(xhr.responseText)
} else {
console.log('伺服器異常')
}
}
xhr.onerror = function(){ //網絡請求斷了 沒網絡 。資料沒法到達伺服器
console.log('伺服器異常')
}
xhr.send()
post
var xhr = new XMLHttpRequest()
xhr.timeout = 3000 //可選,設定xhr請求的逾時時間
xhr.open('POST', '/register', true)
xhr.onload = function(e) {
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
console.log(this.responseText)
}
}
//可選
xhr.ontimeout = function(e) { //請求時間
console.log('請求逾時')
}
//可選
xhr.onerror = function(e) {
console.log('連接配接失敗')
}
//可選
xhr.upload.onprogress = function(e) {
//如果是上傳檔案,可以擷取上傳進度
}
xhr.send('username=qimeng&password=123456')
封裝一個ajax
function ajax(opts){
var url = opts.url
var type = opts.type || 'GET'//預設get
var dataType = opts.dataType || 'json' // 預設json 傳回的資料
var onsuccess = opts.onsuccess || function(){} // 沒有傳遞就是空函數
var onerror = opts.onerror || function(){} //使用者傳遞了用使用者的 沒有就是空函數
var data = opts.data || {}
var dataStr = []
for(var key in data){
dataStr.push(key + '=' + data[key])
}
dataStr = dataStr.join('&')
if(type === 'GET'){
url += '?' + dataStr
}
var xhr = new XMLHttpRequest()
xhr.open(type, url, true)
xhr.onload = function(){
if((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304){
//成功了
if(dataType === 'json'){
onsuccess( JSON.parse(xhr.responseText))
}else{
onsuccess( xhr.responseText)
}
} else {
onerror()
}
}
xhr.onerror = onerror
if(type === 'POST'){
xhr.send(dataStr)
}else{
xhr.send()
}
}
ajax({
url: 'http://api.jirengu.com/weather.php',
data: {
city: '北京'
},
onsuccess: function(ret){
console.log(ret)
},
onerror: function(){
console.log('伺服器異常')
}
})