這是一篇ajax的基礎文章,在半年前我第一次據說ajax,因而去網上查閱了一些資料看看到底是何方聖神,發現根本看不懂。我太弱了。javascript
前幾天纔對ajax瞭解了一些皮毛。因此我想寫一篇0基礎剛開始學技術就能看懂的ajax文章。 但願可以幫助到還沒接觸到ajax的小可愛。經過這篇文章你將瞭解:html
AJAX = Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。java
Ajax:標準讀音 [ˈeɪˌdʒæks] ,中文音譯:阿賈克斯,它是瀏覽器提供的一套方法,可讓用戶在不刷新頁面的狀況下更新用戶數據,提升用戶體驗。也就是在用戶瀏覽網頁的同時局部跟新頁面的數據。node
這裏列舉兩個生活中的例子,讓你們有跟深入的體會。ajax
situation1:好比瀏覽網頁的時候瀏覽到底部有一個‘加載更多’按鈕,以後跟多的數據就會在頁面中渲染出來,在呈現數據的過程當中頁面是沒有刷新的只是在原有數據的後面加上了數據,在不刷新頁面的狀況下向服務器發送請求,而後服務器向客戶端返回數據。編程
situation2: 另一個場景你們更熟悉了,好比某些手遊新人註冊的時候,當你輸入一個用戶名的時候會立馬彈出該用戶名已註冊,而後不得不更換一個用戶名直到用戶名沒有被其餘人註冊過。 若是用戶名沒有被註冊就提示可用。你們應該能想到註冊頁面是表單form。這樣的好處是避免用戶填完全部的註冊信息發送到瀏覽器後再返回錯誤,避免頁面跳轉,避免用戶從新填寫表單的狀況。json
主要做用就是在不刷新頁面的狀況下向服務器端發請求與服務器端進行交互從而更改客戶端頁面的數據或狀態,主要目的就是爲了提升用戶體驗。瀏覽器
傳統的網站中瀏覽器和服務器之間進行通訊的時候瀏覽器沒法繼續進行其餘操做,好比向下拉動頁面。用戶體驗很很差,因此請求的發送和響應的接收不能由瀏覽器本身去完成,若是找一個代理人幫忙作,那樣瀏覽器就能夠響應用戶其餘的操做,豈不美哉?bash
實際上ajax引擎就是這個中間人,ajax幫瀏覽器去發送請求,ajax接收服務器端的響應。當ajax接收到服務器端的數據後咱們再使用dom方法將內容添加到頁面當中。這樣就可無刷新更新數據以及用戶可進行其餘操做。服務器
咱們看下面這幅圖:領導讓祕書幫助本身叫小李,而後本身作別的事情。祕書找啊找找到小李後,小李向領導彙報工做是生活中的常見場景。
若是看到這裏看不下去了記住ajax他不是一門編程語言,而是一種使用現有標準的新方法。 AJAX 最大的優勢是在不從新加載整個頁面的狀況下,能夠與服務器交換數據並更新部分網頁內容。
接下來用代碼看看如何實現ajax這個中間件,這裏涉及到nodeJs和網絡部分的相關知識,若是這兩方面不瞭解後面代碼可能會有些看不懂,不過不要緊,我儘可能把代碼解釋清楚讓你們可以知道相關的一些原理和過程。
ajax實現有四步
咱們看看下面的代碼,在終端中用noedmon命令執行app.js啓動服務器。(若是這句話看不懂就把app當作前面舉例的的第四步中的瀏覽器,app.js中的功能就是瀏覽器返回數據給xhr)
app.js
app.get('/first', (req, res) => {
res.send('Hello, Ajax');
});
html文件:
<script type="text/javascript">
// 1.建立ajax對象
var xhr = new XMLHttpRequest();
// 2.告訴Ajax對象要向哪發送請求,以什麼方式發送請求
// 1)請求方式 2)請求地址
xhr.open('get', 'http://localhost:3000/first');
// 3.發送請求
xhr.send();
// 4.獲取服務器端響應到客戶端的數據
xhr.onload = function (){
console.log(xhr.responseText)
}
</script>
複製代碼
關於第四步的一個說明: 給xhr綁定onload事件,當請求發送成功onload事件就會自動觸發。
代碼分析:
首先執行html文件,執行html文件後客戶端纔會向服務端發送請求,服務器纔會響應這個ajax,若是瀏覽器中看到ajax發送過來的字符串就說明請求是成功的。
咱們看下面的結果在網頁中看到ajax發送過來的字符串說明請求響應成功。
咱們已經知道了ajax實現的四個步驟,其中服務器會向xhr返回數據,數據是以什麼格式返回的呢?
ajax中的x指的雖然是xml,在真實的項目中,服務器端大多數狀況下會以 JSON 對象做爲響應數據的格式。當客戶端拿到響應數據時,要將 JSON 數據和 HTML 字符串進行拼接,而後將拼接的結果展現在頁面中。
在 http 請求與響應的過程當中,不管是請求參數仍是響應內容,若是是對象類型,最終都會被轉換爲對象字符串進行傳輸。
所以咱們要利用JSON.parse()方法將字符串轉換成json數據格式。
下面經過代碼讓服務器返回一個對象,看看不對數據進行處理返回的結果是一個對象仍是一個字符串。
app.js:
app.get('/responseData', (req, res) => {
res.send({"name": "zs"});
});
html:
<script type="text/javascript">
// 1.建立ajax對象
var xhr = new XMLHttpRequest();
// 2.告訴Ajax對象要向哪發送請求,以什麼方式發送請求
// 1)請求方式 2)請求地址
xhr.open('get', 'http://localhost:3000/responseData');
// 3.發送請求
xhr.send();
// 4.獲取服務器端響應到客戶端的數據
xhr.onload = function (){
console.log(typeof xhr.responseText)
// 將JSON字符串轉換爲JSON對象
var responseText = JSON.parse(xhr.responseText);
// 測試:在控制檯輸出處理結果
console.log(responseText)
// 將數據和html字符串進行拼接
var str = '<h2>'+ responseText.name +'</h2>';
// 將拼接的結果追加到頁面中
document.body.innerHTML = str;
}
</script>
複製代碼
代碼分析:
app.js的功能就是服務器向xhr返回{"name": "zs"}這個數據,本應該是json數據但傳輸的時候以字符串傳輸。
代碼中ajax實現步驟仍是前面提到的四步。主要講一講onload方法。
先判斷響應給客戶端數據類型,下圖結果控制檯輸出的第一個值string,就說明對象格式轉成了字符。
而後咱們將字符串轉換爲json數據格式後,控制檯輸出結果看到轉換成了json對象。
再利用h2標籤將字符串進行拼接並使用document下的方法將結果展現到頁面中,也就是結果圖右上角二級標題zs。
向服務請發送請求就會攜帶請求參數,在傳統的網站中請求參數的傳遞都是根據表單來傳遞的,表單提交後表單內容就做爲請求參數向服務器發送請求,不一樣的請求方式請求參數會填寫到不一樣的位置,好比get方式會添加到地址欄中,post方式添加到請求體中。
ajax中須要本身拼接請求參數,根據請求方式的不一樣將請求放到不一樣的位置上。參數名稱與傳統網站相比不變,‘username=111&age=19’(參數名=參數值,多個參數值用&進行分割)。下面將以此介紹get和post兩種請求方式中請求參數是如何傳遞的。
get方法發送的請求參數咱們手動拼接好後添加到open方法中的請求地址這個參數中。
咱們在服務器端寫好一個get請求參數的路由,在地址欄輸入該服務器路由地址,看看會有什麼結果吧。代碼以下:
app.js:
app.get('/get', req, res) => {
res.send(req.query);
});
html:
<script type="text/javascript">
// 獲取按鈕元素
var btn = document.getElementById('btn');
// 獲取姓名文本框
var username = document.getElementById('username');
// 獲取年齡文本框
var age = document.getElementById('age');
// 爲按鈕添加點擊事件
btn.onclick = function () {
// 建立ajax對象
var xhr = new XMLHttpRequest();
// 獲取用戶在文本框中輸入的值
var nameValue = username.value;
var ageValue = age.value;
// 拼接請求參數
var params = 'username='+ nameValue +'&age=' + ageValue;
// 配置ajax對象
xhr.open('get', 'http://localhost:3000/get?'+params);
// 發送請求
xhr.send();
// 獲取服務器端響應的數據
xhr.onload = function () {
console.log(xhr.responseText)
}
}
</script>
複製代碼
代碼分析:
app.js文件中路由中返回的結果就是請求參數, html中監聽按鈕是否被點擊,點擊後就建立了ajax對象,html中的xhr.open方法中對請求參數進行了拼接。若是建立成功瀏覽器就會獲得服務端響應的結果。
執行html文件。咱們看看輸出結果是什麼:
在頁面中輸入姓名111和年齡19.打開開發者工具查看xhr請求,咱們看到請求參數沒有問題。拼接成功,見下圖紅色部分中問號後面部分就是拼接的請求參數。
請求發送成功怎麼判斷服務器有沒有接收到作出響應呢,在html頁面咱們用 console.log(xhr.responseText)答應響應的結果,因此判斷控制檯是否輸出響應的結果就能夠了。頁面中控制檯打印的結果以下,說明服務器接收到了get請求。
post方法發送請求請求參數是要設置在請求體中的,與get方法不一樣,拼接好的請求參數要放到send方法中。同時post請求要在請求報文中明確設置請求參數內容的類型,也就是content-type屬性。
在ajax對象下有一個setRequestHeader方法用來設置請求報文中的請求頭信息。 下面經過代碼來進行演示。建立post方式的請求路由,執行對應的html文件在地址欄中輸入對應的路由地址。看看發生了什麼。
app.js:
app.post('/post', (req, res) => {
res.send(req.body);
});
html:
<script type="text/javascript">
// 獲取按鈕元素
var btn = document.getElementById('btn');
// 獲取姓名文本框
var username = document.getElementById('username');
// 獲取年齡文本框
var age = document.getElementById('age');
// 爲按鈕添加點擊事件
btn.onclick = function () {
// 建立ajax對象
var xhr = new XMLHttpRequest();
// 獲取用戶在文本框中輸入的值
var nameValue = username.value;
var ageValue = age.value;
// 拼接請求參數
var params = 'username='+ nameValue +'&age=' + ageValue;
// 配置ajax對象
xhr.open('post', 'http://localhost:3000/post');
// 設置請求參數格式的類型(post請求必需要設置)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 發送請求
xhr.send(params);
// 獲取服務器端響應的數據
xhr.onload = function () {
console.log(xhr.responseText)
}
}
</script>
複製代碼
代碼分析:
點擊btn按鈕後建立了ajax對象,對ajax對象進行配置,用setRequestHeader對post請求參數的格式進行規定,將post請求發送過去,而後獲取服務端響應的數據將數據打印到控制檯中。執行html文件,咱們將表單中填上數據點擊提交後能夠看到控制檯中輸出了咱們在表單中輸出的數據,也就是服務器的接收到請求並做出了響應。post方法發送請求成功。
客戶端向服務器端傳遞請求參數的格式有兩種。一種是很熟悉的屬性名:屬性值&屬性名:屬性值。另一種就是json數據格式。
不一樣的請求參數格式在setRequestHeader中的Content-type屬性值不同。
格式形式:name=zhangsan&age=20&sex=男
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
複製代碼
格式形式:{name: 'zhangsan', age: '20', sex: '男'}
xhr.setRequestHeader('Content-Type', 'application/json');
複製代碼
來看一個傳遞json字符串的例子吧
app.post('/json', (req, res) => {
res.send(req.body);
});
html:
<script type="text/javascript">
// 1.建立ajax對象
var xhr = new XMLHttpRequest();
// 2.告訴Ajax對象要向哪發送請求,以什麼方式發送請求
// 1)請求方式 2)請求地址
xhr.open('post', 'http://localhost:3000/json');
// 經過請求頭告訴服務器端客戶端向服務器端傳遞的請求參數的格式是什麼
xhr.setRequestHeader('Content-Type', 'application/json');
// JSON.stringify() 將json對象轉換爲json字符串
// 3.發送請求
xhr.send(JSON.stringify({name: 'lisi', age:50}));
// 4.獲取服務器端響應到客戶端的數據
xhr.onload = function (){
console.log(xhr.responseText)
}
</script>
複製代碼
代碼解析: 與常規格式不一樣的是setRequestHeader的參數改變爲'application/json',而後將json對象轉換爲字符串進行傳遞,一樣也是把請求參數放到send函數中。由於json格式只存在post請求參數中。最後獲取到響應將結果打印到控制體。以下圖所示:
ajax獲取服務端的響應其實前面已經出現過了,就是xhr對象下的onload方法。這裏將另一種出現很少的方法。
ajax狀態碼與http狀態碼(不知道http狀態碼能夠本身查)不一樣。ajax狀態碼是建立一個ajax對象,配置ajax對象,發送請求,以及接收完服務端響應數據的過程當中對應的一個數值。這個數值就是ajax狀態碼。經過狀態碼咱們知道當前請求進行到了哪一步。
ajax狀態碼主要有如下五種:
在xhr下有一個readyState存貯了ajax狀態碼。咱們能夠經過判斷ajax狀態碼狀態讓客戶端作出響應。
下面經過代碼展現另一種經過onreadystatechange獲取服務器端響應的操做。
<script type="text/javascript">
var xhr = new XMLHttpRequest();
// 0 已經建立了ajax對象 可是尚未對ajax對象進行配置
console.log(xhr.readyState);
xhr.open('get', 'http://localhost:3000/readystate');
// 1 已經對ajax對象進行配置 可是尚未發送請求
console.log(xhr.readyState);
xhr.send();
// 當ajax狀態碼發生變化的時候出發
xhr.onreadystatechange = function() {
// 2 請求已經發送了
// 3 已經接收到服務器端的部分數據了
// 4 服務器端的響應數據已經接收完成
console.log(xhr.readyState);
// 對ajax狀態碼進行判斷 若是狀態碼的值爲4就表明數據已經接收完成了
if (xhr.readyState == 4) {
console.log(xhr.responseText);
}
}
<!--xhr.send();-->
</script>
複製代碼
代碼說明:上面的註釋很清楚了,若是有問題能夠評論區騷擾我哈。
onreadystatechange方法是在狀態碼發生變化的時候觸發的,若是咱們把send方法寫在最後就會報錯。
由於onreadystatechange方法是狀態碼發生變化的時候該方法纔可以被觸發,若是放在send方法放在前面就沒有什麼做用了,由於send方法雖然會引發狀態碼的變化,可是onreadystatechange方法在執行上下文中只是一個沒有被賦值變量,沒法執行。
就好像你要用手機聽歌可是手機沒有電沒法聽歌同樣。這裏就比如send觸發的時候狀態碼在變化可是你沒有自動打印狀態碼的函數同樣。
改進方法:因此咱們把send方法放在後面,這個時候執行棧中就有了onreadystatechange這個函數。就不會報錯。
咱們對上面的代碼進行修改,這裏直接上結果。沒有報錯,而且狀態爲4的時候輸出了服務器響應的結果。完美。
目前咱們知道了兩種方法,一種是經過判斷狀態碼是否發生變化就觸發的 onreadystatechange函數,另一種是前面提到的瀏覽器接收完響應就會觸發的onload方法,這兩總方法有什麼差別呢?我來給您畫個表吧
區別 | onload事件 | onreadystatechange |
---|---|---|
是否兼容ie低版本 | 不兼容 | 兼容 |
是否要判斷ajax狀態 | 不須要 | 須要 |
被調用次數 | 一次 | 屢次 |
經過表格咱們知道onload相對於更爲簡單效率高,可是在ie低版本瀏覽器可使用onreadystatechange。
文章寫完了,回顧一下,最開始介紹ajax是什麼,他是編程語言嗎?他的主要做用是什麼?原理是什麼?而後如何使用ajax,經過一些代碼介紹了ajax和服務器進行交互,而後瀏覽器又是如何拿到結果渲染頁面的。其實整片文章就是講開篇的第二章張圖,在此基礎上進行了擴充。
再看看這幅圖吧,但願能給你帶來更深的啓發和思考。歡迎你們的評論區留言談談感悟。
若是有看不明白的地方就麻煩在評論區告訴我唄,有理解不到位的地方十分歡迎指正。
這篇文章是一個簡單的入門,後續深刻學習仍是必不可少滴。
若是喜歡以爲有用,記得留下美麗的痕(dian)跡(zan)哦。