淺析Ajax語法
Ajax是目前很普遍的一門技術(shù),也是很值得探討和研究的一門技術(shù)。本文將針對(duì)Ajax的發(fā)展過程并結(jié)合其在不同庫框架中的使用方式來和大家分享下Ajax的那些新老語法。
Ajax簡(jiǎn)介
Ajax全稱為“Asynchronous Javascript And XML”, 即“異步JavaScript和XML”的意思。通過Ajax我們可以向服務(wù)器發(fā)送請(qǐng),在不阻塞頁面的情況下進(jìn)行數(shù)據(jù)交互,也可以理解為異步數(shù)據(jù)傳輸。在Ajax的幫助下我們的網(wǎng)頁只需局部刷新即可更新數(shù)據(jù)的顯示,減少了不必要的數(shù)據(jù)量,大大提高了用戶體驗(yàn),縮短了用戶等待的時(shí)間,使得web應(yīng)用程序更小、更快,更友好。
當(dāng)然以上都是司空見慣的內(nèi)容了,作為一名合格的開發(fā)人員基本都再熟悉不過了,這里只為那些剛?cè)腴T的新手做一個(gè)簡(jiǎn)單的介紹。更多的關(guān)于Ajax的簡(jiǎn)介請(qǐng)移步W3School進(jìn)行了解:http://www.w3school.com.cn/php/php_ajax_intro.asp
原生Ajax
基本上所有現(xiàn)代的瀏覽器都支持原生Ajax的功能,下面就來詳細(xì)介紹下利用原生JS我們?cè)鯓觼戆l(fā)起和處理Ajax請(qǐng)求。
1.獲取XMLHttpRequest對(duì)象
var xhr = new XMLHttpRequest(); // 獲取瀏覽器內(nèi)置的XMLHttpRequest對(duì)象
如果你的項(xiàng)目應(yīng)用不考慮低版本IE,那么可以直接用上面的方法,所有現(xiàn)代瀏覽器 (Firefox、Chrome、Safari 以及 Opera) 都內(nèi)建了 XMLHttpRequest 對(duì)象。如果需要兼容老版本IE(IE5、IE6),那么可以使用 ActiveX 對(duì)象:
var xhr; if (window.XMLHttpRequest) { xhr=new XMLHttpRequest(); } else if (window.ActiveXObject) { // 兼容老版本瀏覽器 xhr=new ActiveXObject("Microsoft.XMLHTTP"); }
2.參數(shù)配置
有了XMLHttpRequest對(duì)象,我們還需要配置一些請(qǐng)求的參數(shù)信息來完成數(shù)據(jù)交互,利用open方法即可:
var xhr; if (window.XMLHttpRequest) { xhr=new XMLHttpRequest(); } else if (window.ActiveXObject) { xhr=new ActiveXObject("Microsoft.XMLHTTP"); } if (xhr) { xhr.open('GET', '/test/', true); // 以GET請(qǐng)求的方式向'/test/'路徑發(fā)送異步請(qǐng)求 }
open方法為我們創(chuàng)建了一個(gè)新的http請(qǐng)求,其中第一個(gè)參數(shù)為請(qǐng)求方式,一般為'GET'或'POST';第二個(gè)參數(shù)為請(qǐng)求url;第三個(gè)參數(shù)為是否異步,默認(rèn)為true。
3.發(fā)送請(qǐng)求
配置完了基本參數(shù)信息,我們直接調(diào)用send方法發(fā)送請(qǐng)求,代碼如下:
var xhr; if (window.XMLHttpRequest) { xhr=new XMLHttpRequest(); } else if (window.ActiveXObject) { xhr=new ActiveXObject("Microsoft.XMLHTTP"); } if (xhr) { xhr.open('GET', '/test/', true); xhr.send(); // 調(diào)用send方法發(fā)送請(qǐng)求 }
這里需要注意的是如果使用GET方法傳遞參數(shù),我們可以直接將參數(shù)放在url后面,比如'/test/?name=luozh&size=12';如果使用POST方法,那么我們的參數(shù)需要寫在send方法里,如:
xhr.open('POST', '/test/', true); xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded"); // 將請(qǐng)求頭設(shè)置為表單方式提交 xhr.send('name=luozh&size=12');
最終會(huì)以Form Data的形式傳遞:
如果不設(shè)置請(qǐng)求頭,原生Ajax會(huì)默認(rèn)使用Content-Type是'text/plain;charset=UTF-8'的方式發(fā)送數(shù)據(jù),如果按照上面的參數(shù)書寫形式,我們最終傳輸?shù)男问竭@樣的:
顯然這并不是服務(wù)器期望的數(shù)據(jù)格式,我們可以這樣寫:
xhr.open('POST', '/test/', true); xhr.send(JSON.stringify({name: 'luozh', size: 12}));
最終傳輸?shù)母袷饺缦拢?/p>
這樣我們可以直接傳遞JSON字符串給后臺(tái)處理,當(dāng)然后臺(tái)也許進(jìn)行相應(yīng)配置。
4.監(jiān)測(cè)狀態(tài)
發(fā)送完Ajax請(qǐng)求之后,我們需要針對(duì)服務(wù)器返回的狀態(tài)進(jìn)行監(jiān)測(cè)并進(jìn)行相應(yīng)的處理,這里我們需要使用onreadystatechange方法,代碼如下:
var xhr; if (window.XMLHttpRequest) { xhr=new XMLHttpRequest(); } else if (window.ActiveXObject) { xhr=new ActiveXObject("Microsoft.XMLHTTP"); } if (xhr) { xhr.open('GET', '/test/', true); // 以GET請(qǐng)求的方式向'/test/'路徑發(fā)送異步請(qǐng)求 xhr.send(); xhr.onreadystatechange = function () { // 利用onreadystatechange監(jiān)測(cè)狀態(tài) if (xhr.readyState === 4) { // readyState為4表示請(qǐng)求響應(yīng)完成 if (xhr.status === 200) { // status為200表示請(qǐng)求成功 console.log('執(zhí)行成功'); } else { console.log('執(zhí)行出錯(cuò)'); } } } }
上面我們利用onreadystatechange監(jiān)測(cè)狀態(tài),并在內(nèi)部利用readyState獲取當(dāng)前的狀態(tài)。readyState一共有5個(gè)階段,當(dāng)其為4時(shí)表示響應(yīng)內(nèi)容解析完成,可以在客戶端調(diào)用了。當(dāng)readyState為4時(shí),我們又通過status來獲取狀態(tài)碼,狀態(tài)碼為200時(shí)執(zhí)行成功代碼,否則執(zhí)行出錯(cuò)代碼。
當(dāng)然我們可以用onload來代替onreadystatechange等于4的情況,因?yàn)閛nload只在狀態(tài)為4的時(shí)候才被調(diào)用,代碼如下:
xhr.onload = function () { // 調(diào)用onload if (xhr.status === 200) { // status為200表示請(qǐng)求成功 console.log('執(zhí)行成功'); } else { console.log('執(zhí)行出錯(cuò)'); } }
然而需要注意的是,IE對(duì)onload這個(gè)屬性的支持并不友好。
除了onload還有:
- onloadstart
- onprogress
- onabort
- ontimeout
- onerror
- onloadend
等事件,有興趣的同學(xué)可以親自去實(shí)踐它們的用處。
以上便是原生Ajax請(qǐng)求數(shù)據(jù)的常見代碼。
其他庫框架中的Ajax
1.jQuery中的Ajax
jQuery作為一個(gè)使用人數(shù)最多的庫,其Ajax很好的封裝了原生Ajax的代碼,在兼容性和易用性方面都做了很大的提高,讓Ajax的調(diào)用變得非常簡(jiǎn)單。下面便是一段簡(jiǎn)單的jQuery的Ajax代碼:
$.ajax({ method: 'GET', // 1.9.0本版前用'type' url: "/test/", dataType: 'json' }) .done(function() { console.log('執(zhí)行成功'); }) .fail(function() { console.log('執(zhí)行出錯(cuò)'); })
與原生Ajax不同的是,jQuery中默認(rèn)的Content-type是'application/x-www-form-urlencoded; charset=UTF-8', 想了解更多的jQuery Ajax的信息可以移步官方文檔:http://api.jquery.com/jquery.ajax/
2.Vue.js中的Ajax
Vue.js作為目前熱門的前端框架,其實(shí)其本身并不包含Ajax功能,而是通過插件的形式額外需要在項(xiàng)目中引用,其官方推薦Ajax插件為vue-resource,下面便是vue-resource的請(qǐng)求代碼:
Vue.http.get('/test/').then((response) => { console.log('執(zhí)行成功'); }, (response) => { console.log('執(zhí)行出錯(cuò)'); });
vue-resource支持Promise API,同時(shí)支持目前的Firefox, Chrome, Safari, Opera 和 IE9+瀏覽器,在瀏覽器兼容性上不兼容IE8,畢竟Vue本身也不兼容IE8。想了解更多的vue-resource的信息可以移步github文檔:https://github.com/vuejs/vue-resource
3.Angular.js中的Ajax
這里Angular.js中的Ajax主要指Angular的1.×版本,因?yàn)锳ngular2目前還不建議在生產(chǎn)環(huán)境中使用。
var myApp = angular.module('myApp',[]); var myCtrl = myApp.controller('myCtrl',['$scope','$http',function($scope, $http){ $http({ method: 'GET', url: '/test/', headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'} }).success(function (data) { console.log('執(zhí)行成功'); }).error(function () { console.log('執(zhí)行出錯(cuò)'); }); }]);
在Angular中,我們需要在控制器上注冊(cè)一個(gè)$http的事件,然后才能在內(nèi)部執(zhí)行Ajax。Angular的Ajax默認(rèn)的Content-type是'application/json;charset=UTF-8',所以如果想用表單的方式提交還需設(shè)置下headers屬性。想了解更多的Angular Ajax的信息可以移步官方文檔:https://docs.angularjs.org/api/ng/service/$http(可能需要FQ)
4.React中的Ajax
在React中我比較推薦使用fetch來請(qǐng)求數(shù)據(jù),當(dāng)然其不僅適用于React,在任何一種框架如上面的Vue、Angular中都可以使用,因?yàn)槠湟呀?jīng)被目前主流瀏覽器所支持,至于其主要功能和用法,我在下面會(huì)做下講解。
Fetch API
Fetch API 是基于 Promise 設(shè)計(jì),由于Promise的瀏覽器兼容性問題及Fetch API本身的兼容問題,一些瀏覽器暫時(shí)不支持Fetch API,瀏覽器兼容圖如下:
當(dāng)然我們可以通過使用一些插件來解決兼容性問題,比如:fetch-polyfill、es6-promise、fetch-ie8等。
使用Fetch我們可以非常便捷的編寫Ajax請(qǐng)求,我們用原生的XMLHttpRequst對(duì)象和Fetch來比較一下:
XMLHttpRequst API
// XMLHttpRequst API var xhr = new XMLHttpRequest(); xhr.open('GET', '/test/', true); xhr.onload = function() { console.log('執(zhí)行成功'); }; xhr.onerror = function() { console.log('執(zhí)行出錯(cuò)'); }; xhr.send();
Fetch API
fetch('/test/').then(function(response) { return response.json(); }).then(function(data) { console.log('執(zhí)行成功'); }).catch(function(e) { console.log('執(zhí)行出錯(cuò)'); });
可以看出使用Fetch后我們的代碼更加簡(jiǎn)潔和語義化,鏈?zhǔn)秸{(diào)用的方式也使其更加流暢和清晰。隨著瀏覽器內(nèi)核的不斷完善,今后的XMLHttpRequest會(huì)逐漸被Fetch替代。關(guān)于Fetch的詳細(xì)介紹可以移步:https://segmentfault.com/a/1190000003810652
跨域Ajax
介紹了各種各樣的Ajax API,我們不能避免的一個(gè)重要問題就是跨域,這里重點(diǎn)講解下Ajax跨域的處理方式。
處理Ajax跨域問題主要有以下4種方式:
- 利用iframe
- 利用JSONP
- 利用代理
- 利用HTML5提供的XMLHttpRequest Level2
第1和第2種方式大家應(yīng)該都非常熟悉,都屬于前端的活,這里就不做介紹了,這里主要介紹第3和第4種方式。
利用代理的方式可以這樣理解:
通過在同域名下的web服務(wù)器端創(chuàng)建一個(gè)代理:
北京服務(wù)器(域名:www.beijing.com)
上海服務(wù)器(域名:www.shanghai.com)
比如在北京的web服務(wù)器的后臺(tái)(www.beijing.com/proxy-shanghaiservice.php)來調(diào)用上海服務(wù)器(www.shanghai.com/services.php)的服務(wù),然后再把訪問結(jié)果返回給前端,這樣前端調(diào)用北京同域名的服務(wù)就和調(diào)用上海的服務(wù)效果相同了。
利用XMLHttpRequest Level2的方式需要后臺(tái)將請(qǐng)求頭進(jìn)行相應(yīng)配置:
// php語法 header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET,POST');
以上的*號(hào)可以替換成允許訪問的域名,*表示所有域名都可以訪問。
由此可見,第3和第4種方式主要是后臺(tái)的活,前端只需調(diào)用就可以。
總結(jié)
無論Ajax的語法多么多變,無論庫和框架如何封裝Ajax,其只是一種實(shí)現(xiàn)異步數(shù)據(jù)交互的工具,我們只需理解原生JS中Ajax的實(shí)現(xiàn)原理,了解XMLHttpRequest及promise的概念和流程,便可以輕松的在數(shù)據(jù)異步交互的時(shí)代游刃有余。
以上就是本文的全部內(nèi)容,希望對(duì)大家有所幫助,同時(shí)也希望多多支持腳本之家!
- Ajax的使用代碼解析
- PHP AjaxForm提交圖片上傳并顯示圖片源碼
- JS 攔截全局ajax請(qǐng)求實(shí)例解析
- Ajax遍歷jSon后對(duì)每一條數(shù)據(jù)進(jìn)行相應(yīng)的修改和刪除(代碼分享)
- AJAX工作原理及優(yōu)缺點(diǎn)詳解
- AngularJS實(shí)現(xiàn)ajax請(qǐng)求的方法
- 使用Ajax生成的Excel文件并下載的實(shí)例
- Ajax的概述與實(shí)現(xiàn)過程
- AJAX請(qǐng)求隊(duì)列實(shí)現(xiàn)
- Ajax讀取txt并對(duì)txt內(nèi)容進(jìn)行分頁顯示功能
- 在Thinkphp中使用ajax實(shí)現(xiàn)無刷新分頁的方法
- jstree創(chuàng)建無限分級(jí)樹的方法【基于ajax動(dòng)態(tài)創(chuàng)建子節(jié)點(diǎn)】
- JavaScript將base64圖片轉(zhuǎn)換成formData并通過AJAX提交的實(shí)現(xiàn)方法
- jQuery插件ajaxFileUpload異步上傳文件
相關(guān)文章
js禁止document element對(duì)象選中文本實(shí)現(xiàn)代碼
禁止document element對(duì)象選中文本在某在情況下還是很有必要的接下來本文將使用js實(shí)現(xiàn),感興趣的各位可以參考下哈2013-03-03微信小程序自定義菜單導(dǎo)航實(shí)現(xiàn)樓梯效果
在html開發(fā)中,我們可以用到a標(biāo)簽錨點(diǎn)實(shí)現(xiàn),jq的動(dòng)畫相結(jié)合實(shí)現(xiàn)類似效果。在框架中vant UI框架也為我們實(shí)現(xiàn)了這一效果。接下來通過本文給大家介紹微信小程序自定義菜單導(dǎo)航實(shí)現(xiàn)樓梯效果,感興趣的朋友一起看看吧2021-12-12如何使用JavaScript實(shí)現(xiàn)無縫滾動(dòng)自動(dòng)播放輪播圖效果
這篇文章主要介紹了如何使用JavaScript實(shí)現(xiàn)“無縫滾動(dòng) 自動(dòng)播放”輪播圖效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08Javascript 高性能之遞歸,迭代,查表法詳解及實(shí)例
這篇文章主要介紹了Javascript 高性能之遞歸,迭代,查表法詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-01-01IE8提示Invalid procedure call or argument 異常的解決方法
某臺(tái)機(jī)器上,訪問公司的好幾個(gè)產(chǎn)品網(wǎng)站,都拋出很多 Invalid procedure call or argument ,跟進(jìn)了下,情況最后簡(jiǎn)化為2012-09-09js禁止Backspace鍵使瀏覽器后退的實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猨s禁止Backspace鍵使瀏覽器后退的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09