啥都不說了,挺華爲就完事了,山姆大叔有點過度了,我相信華爲能挺過來javascript
啊,賈克斯???如今從事前端的小夥伴不可能不知道這個,若是真不知道這個詞,那我以爲你還稱不上前端開發🙄css
此賈克斯非彼賈克斯,前端說的啊賈克斯是Asynchronous javaScript + XML的簡寫,Ajax在很大程度上讓前端發展加快了腳步,他的出現和使用,但是說是前端史上的里程碑html
Ajax橫空出世,打破了先後端交互的時候須要從新加載頁面,就是整頁刷新,咱們能夠經過Ajax技術直接在頁面不刷新的狀況下,發出請求,獲取返回數據,而後經過js操做Dom更改頁面內容。前端
也是Ajax出現了之後,才促成了日後的先後端分離,再也不是前端只負責切圖,只是給後端同窗提供模板,而後數據由後端同窗添加上。咱們前端今後也能夠再也不依賴後端同窗模板套數據了,咱們本身就能夠完成。java
那咱們是如何實現這個無刷新獲取數據呢,這就要基於一個對象了————XMLHttpRequestjquery
Ajax說白了不是新技術,只是一種解決方案,跟jsonp差很少,是基於XMLHttpRequest對象的一個獲取後端數據的方案,那咱們來看看怎麼寫的吧(本文不涉及兼容ie等部分瀏覽器,走主流)ios
(() => {
// 獲取頁面上須要發請求的按鈕
let btn = document.querySelector('.getAjaxBtn');
// 添加事件
btn.addEventListener('click', createXHR)
// 咱們ajax的主體函數
function createXHR() {
// new一個XMLHttpRequest實例
var xhr = new XMLHttpRequest();
// 第一步使用open方法,接收三個參數
// 第一個參數是請求方法名(get,post等)
// 第二個參數是須要請求的接口地址
// 第三個參數是設置請求是不是異步,通常都是都是發送異步請求,同步請求可能會阻塞頁面
// 咱們先來看同步請求
xhr.open('get', '/api/get', false);
// open方法只是設置參數,並不會發送請求
// 而請求是由send()方法發送的,而且接收一個參數,就是須要發送到服務端的數據
// 若是沒有須要發送到服務端的數據,必須傳入null,由於有些瀏覽器不準要這個參數
xhr.send(null)
}
})()
複製代碼
這樣寫的話,咱們就在一個按鈕上綁定了一個發送get請求的方法,只要咱們點擊這個按鈕,就會發送請求,那咱們來看看是什麼效果 面試
其實很簡單是否是,沒錯,這樣咱們確實就已經發送了一個get請求了,那咱們發送請求是爲了什麼呢,固然是爲了獲取到數據,那咱們看到接口已經返回了字符串'恭喜你,你發送了一個get請求,真棒!'
,那咱們怎麼能拿到這個數據呢,看下面ajax
其實咱們在收到服務端響應的時候,就已經拿到了數據,響應的數據會自動填充到XHR對象中,但咱們何時才能知道這個數據已經填充到XHR對象中呢??這個時候咱們就須要一個相似於監聽函數的事件————readystatechange事件,z這個事件當readystate狀態改變,就會執行一次。咱們還須要一個知道請求發送狀態的屬性————readystate,還有一個請求狀態碼屬性————statusjson
狀態碼就是200、404以及500這種的,在這就不細說了,主要說說readystate有什麼狀態:
看了一下這接個狀態,好像咱們如今須要的是4這個狀態,接收到了所有的數據,而後咱們再作一個邏輯處理,上面的請求咱們是同步請求,如今咱們改改裝一下
(() => {
// 獲取頁面上須要發請求的按鈕
let btn = document.querySelector('.getAjaxBtn');
// 添加事件
btn.addEventListener('click', createXHR)
// 咱們ajax的主體函數
function createXHR() {
// new一個XMLHttpRequest實例
var xhr = new XMLHttpRequest();
// 第一步使用open方法,接收三個參數
// 第一個參數是請求方法名(get,post等)
// 第二個參數是須要請求的接口地址
// 第三個參數是設置請求是不是異步,通常都是都是發送異步請求,同步請求可能會阻塞頁面
// 咱們先來看同步請求
xhr.open('get', '/api/get', true);
// 咱們爲xhr添加一個readyState值改變就執行的監聽事件
// 這個事件還必須寫在send()方法前面
xhr.onreadystatechange = function () {
// 當readyState值爲4就是接收到了所有返回數據,而且http狀態碼是200多的成功,或者是304的緩存,這時候就判斷已是成功拿到了應該返回的數據
if (xhr.readyState === 4 ) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304 ) {
// 輸出數據。responseText是做爲響應主體被返回的文本
alert(xhr.responseText)
} else {
alert('請求不成功')
}
}
}
// open方法只是設置參數,並不會發送請求
// 而請求是由send()方法發送的,而且接收一個參數,就是須要發送到服務端的數據
// 若是沒有須要發送到服務端的數據,必須傳入null,由於有些瀏覽器不準要這個參數
xhr.send(null)
}
})()
複製代碼
這樣咱們就成功的拿到了返回的數據而且彈出來了,咱們不只拿到數據能夠彈出,咱們就能夠進行一些更厲害的邏輯處理或者改變頁面內容了。
固然了,也許你get請求的時候須要發送一些數據給服務端,多是什麼頁碼或者頁面須要多少條數據等,咱們這個時候只要在open()方法中傳入的url上面拼上就好了,相似/api/get?pageNum=1&pageSize=20
這樣的url。
咱們寫的服務端就是返回請求中的數據,咱們也能看到,咱們也收到了返回來的數據了
post請求,咱們應該接觸過form的表單提交,咱們post請求傳輸的數據必須是通過encodeURIComponent
轉碼的,並且當咱們接收到一個json對象,咱們須要將他進行轉換
(() => {
let btn = document.querySelector('.getAjaxBtn');
btn.addEventListener('click', createXHR);
// 咱們須要轉換的數據,真實場景咱們應該是傳進來的,或者是獲取到的用戶輸入的數據
let data = {
method: 'post',
a: 'a',
b: 123,
}
function createXHR() {
var xhr = new XMLHttpRequest();
xhr.open('post', '/api/post', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 ) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304 ) {
alert(xhr.responseText)
} else {
alert('請求不成功')
}
}
}
// 模仿表單提交,設置content-type,咱們須要從新設置請求頭,讓服務端能知道咱們傳的是個什麼數據
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
// send()方法須要傳入的數據應該通過處理
xhr.send(transformData(data))
}
// 處理傳入json對象轉換格式
/** * 例如這個樣的json * { method: 'post', a: 'a', b: 123, } */
// 轉換格式爲
// method=post&a=a&b=123
// 這樣
function transformData(data) {
let newData = [];
for (let key in data) {
newData.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
}
return newData.join('&')
}
})()
複製代碼
上面就是咱們進行的post請求,咱們能看到咱們發送了一了個Form Data,而後服務端拿到了這個數據,而且咱們拿到了會返回來的數據,也就是咱們發送給服務端的數據
固然除了我上面說到的一些屬性和方法,XHR還有不少我沒有介紹到的方法和屬性,這裏就說一下幾個經常使用的吧
若是咱們這麼寫,咱們會發現很麻煩,並且若是咱們沒有考慮周全,這個請求方法會很糟糕,隱藏一些未知問題
技術,向來都是爲了提升效率,或者也能夠說是爲懶人研究的
如今已經有很好的成熟的開源庫替咱們封裝好了ajax請求方法,例如「尚能飯否的jQuery」以及隨着框架模塊大放異彩的「Axios」,他們的使用方法相對簡單不少,也不用咱們本身去處理一些邏輯問題,邊界問題。
咱們來看看這兩個是多麼簡單實現的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<title>Ajax</title>
</head>
<body>
<button class="postAxiosBtn">發送axios post請求</button>
<button class="getAxiosBtn">發送axios get請求</button>
<button class="postJqueryBtn">發送jQuery post請求</button>
<button class="getJqueryBtn">發送jQuery get</button>
<script> var postAxiosBtn = $('.postAxiosBtn'), getAxiosBtn = $('.getAxiosBtn'), postJqueryBtn = $('.postJqueryBtn'), getJqueryBtn = $('.getJqueryBtn'); postAxiosBtn.click(() => { axios.post('/api/post', { data: { method: 'post', a: 'a', b: 123, } }).then(res => { console.log(res) }) }) getAxiosBtn.click(() => { axios.get('/api/get', { params: { pageNum: 1, pageSize: 20 } }).then(res => { console.log(res) }) }) postJqueryBtn.click(() => { $.post('/api/post', {method: 'post', a: 'a', b: 123}, function (data, status) { console.log(data) console.log(status) }) }) getJqueryBtn.click(() => { $.get('/api/get', {pageNum: 1, pageSize: 20}, function (data, status) { console.log(data) console.log(status) }) }) </script>
</body>
</html>
複製代碼
封裝庫使用起來就是這麼簡單!!!
想來你們也都知道fetch這個api了,js新出的一個api,對標的就是XMLHttpRequest,可是相比於XMLHttpRequest,fetch的使用很人性化了,並且自帶promise語法,咱們不用再用什麼回調的方法了,可是fetch再去跟axios這種封裝XMLHttpRequest的庫來講,使用方法上還有有很大的差距吧。
但我相信之後封裝fetch這種的庫會愈來愈多的,如今雖然有,可是我感受用的人尚未要使用axios那種程度😜
如今已經不多會用到純手寫原生Ajax了,都會用已經寫好的封裝庫了,可是面試的時候不乏也會遇到讓你手寫的,這就很頭疼了
尤大的回答不無道理,可是能說上來或者手寫原生Ajax的人,絕對是對只是有着一種執着
知其然也得知其因此然,寫僞代碼我感受也是說的過去的,起碼對大的思路要了解,一些api接不住無所謂,js、css那麼多屬性,方法,要是都記下來確定是不可能的,可是仍是能知道有這個東西的存在,查的時候也好查,是否是🤠
我是前端戰五渣,一個前端界的小學生。