天天看點

好程式員web前端教育訓練分享JavaScript學習筆記ajax及ajax封裝

  好程式員web前端教育訓練分享JavaScript學習筆記ajax及ajax封裝,ajax 全名 async javascript and XML

  是前背景互動的能力

  也就是我們用戶端給服務端發送消息的工具,以及接受響應的工具

  是一個 預設異步 執行機制的功能

  AJAX 的優勢

.  不需要插件的支援,原生 js 就可以使用

.  使用者體驗好(不需要重新整理頁面就可以更新資料)

.  減輕服務端和帶寬的負擔

.  缺點: 搜尋引擎的支援度不夠,因為資料都不在頁面上,搜尋引擎搜尋不到

  AJAX 的使用

  在 js 中有内置的構造函數來建立 ajax 對象

  建立 ajax 對象以後,我們就使用 ajax 對象的方法去發送請求和接受響應

建立一個 ajax 對象

// IE9及以上const xhr = new XMLHttpRequest()​// IE9以下const xhr = new ActiveXObject('Mricosoft.XMLHTTP')

上面就是有了一個 ajax 對象

我們就可以使用這個 xhr 對象來發送 ajax 請求了

配置連結資訊

const xhr = new XMLHttpRequest()​// xhr 對象中的 open 方法是來配置請求資訊的// 第一個參數是本次請求的請求方式 get / post / put / ...// 第二個參數是本次請求的 url // 第三個參數是本次請求是否異步,預設 true 表示異步,false 表示同步// xhr.open('請求方式', '請求位址', 是否異步)xhr.open('get', './data.php')

上面的代碼執行完畢以後,本次請求的基本配置資訊就寫完了

發送請求

const xhr = new XMLHttpRequest()xhr.open('get', './data.php')​// 使用 xhr 對象中的 send 方法來發送請求xhr.send()

上面代碼是把配置好資訊的 ajax 對象發送到服務端

一個基本的 ajax 請求

一個最基本的 ajax 請求就是上面三步

但是光有上面的三個步驟,我們确實能把請求發送的到服務端

如果服務端正常的話,響應也能回到用戶端

但是我們拿不到響應

如果想拿到響應,我們有兩個前提條件

.本次 HTTP 請求是成功的,也就是我們之前說的 http 狀态碼為 200 ~ 299

.ajax 對象也有自己的狀态碼,用來表示本次 ajax 請求中各個階段

ajax 狀态碼

ajax 狀态碼 - xhr.readyState

是用來表示一個 ajax 請求的全部過程中的某一個狀态

readyState === 0: 表示未初始化完成,也就是 open 方法還沒有執行

readyState === 1: 表示配置資訊已經完成,也就是執行完 open 之後

readyState === 2: 表示 send 方法已經執行完成

readyState === 3: 表示正在解析響應内容

readyState === 4: 表示響應内容已經解析完畢,可以在用戶端使用了

這個時候我們就會發現,當一個 ajax 請求的全部過程中,隻有當 readyState === 4 的時候,我們才可以正常使用服務端給我們的資料

是以,配合 http 狀态碼為 200 ~ 299 

一個 ajax 對象中有一個成員叫做 xhr.status

這個成員就是記錄本次請求的 http 狀态碼的

兩個條件都滿足的時候,才是本次請求正常完成

readyStateChange

在 ajax 對象中有一個事件,叫做 readyStateChange 事件

這個事件是專門用來監聽 ajax 對象的 readyState 值改變的的行為

也就是說隻要 readyState 的值發生變化了,那麼就會觸發該事件

是以我們就在這個事件中來監聽 ajax 的 readyState 是不是到 4 了

const xhr = new XMLHttpRequest()xhr.open('get', './data.php')​xhr.send()​xhr.onreadyStateChange = function () {

// 每次 readyState 改變的時候都會觸發該事件 // 我們就在這裡判斷 readyState 的值是不是到 4 // 并且 http 的狀态碼是不是 200 ~ 299 if (xhr.readyState === 4 && /^2d{2|$/.test(xhr.status)) {

// 這裡表示驗證通過 // 我們就可以擷取服務端給我們響應的内容了 }}

responseText

ajax 對象中的 responseText 成員

就是用來記錄服務端給我們的響應體内容的

是以我們就用這個成員來擷取響應體内容就可以

if (xhr.readyState === 4 && /^2d{2|$/.test(xhr.status)) {

// 我們在這裡直接列印 xhr.responseText 來檢視服務端給我們傳回的内容 console.log(xhr.responseText)

}}

使用 ajax 發送請求時攜帶參數

我們使用 ajax 發送請求也是可以攜帶參數的

參數就是和背景互動的時候給他的一些資訊

但是攜帶參數 get 和 post 兩個方式還是有差別的

發送一個帶有參數的 get 請求

get 請求的參數就直接在 url 後面進行拼接就可以

const xhr = new XMLHttpRequest()// 直接在位址後面加一個 ?,然後以 key=value 的形式傳遞// 兩個資料之間以 & 分割xhr.open('get', './data.php?a=100&b=200')​xhr.send()

這樣服務端就能接受到兩個參數

一個是 a,值是 100

一個是 b,值是 200

發送一個帶有參數的 post 請求

post 請求的參數是攜帶在請求體中的,是以不需要再 url 後面拼接

const xhr = new XMLHttpRequest()xhr.open('post', './data.php')​// 如果是用 ajax 對象發送 post 請求,必須要先設定一下請求頭中的 content-type// 告訴一下服務端我給你的是一個什麼樣子的資料格式xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')​// 請求體直接再 send 的時候寫在 () 裡面就行// 不需要問号,直接就是 'key=value&key=value' 的形式xhr.send('a=100&b=200')

application/x-www-form-urlencoded 表示的資料格式就是 key=value&key=value

同源政策

同源政策是由浏覽器給的

浏覽器不允許我們向别人發送請求,隻能向自己的伺服器發送請求

當我們想向别人的伺服器發送請求的時候,就會被浏覽器阻止了

什麼是 “别人的伺服器” 呢?

當 請求協定/域名/端口号 有任意一個不同的時候,那麼就算是别人的伺服器

這個時候就會觸發同源政策

我們管觸發了 同源政策 的請求叫做跨域請求

實作一個跨域請求

有的時候我們是需要實作跨域請求的

我們需要多個伺服器給一個頁面提供資料

那麼這個時候我們就要想辦法解決跨域問題

JSONP

jsonp 是我們實作跨域請求的手段,是把我們之前的東西組合在一起使用的技術手段而已

利用的是 script 标簽來實作

script 标簽的本質

浏覽器給我們提供了一個 script 标簽

它的本質就是請求一個外部資源,是不受到同源政策的影響的

同時 script 标簽的 src 屬性,也是一種請求,也能被伺服器接收到

并且:

script标簽的src屬性請求回來的東西是一個字元串,浏覽器會把這個字元串當作 js 代碼來執行

是以我們就可以利用這個 script 标簽的 src 屬性來進行跨域請求了

配置代理(了解)

代理,分成兩種,正向代理和反向代理

正向代理

有一個用戶端需要向一個非同源的伺服器B發送請求

我們搭建一個和用戶端同源的伺服器A

當用戶端發送請求的時候,由伺服器A來接受

再由伺服器A向伺服器B發送請求,因為 同源政策是由浏覽器給的,伺服器之間沒有

伺服器B接受到請求以後,會處理請求,并把響應傳回給伺服器A

再由伺服器A把響應給到用戶端就可以了

我們就可以用這個方式來進行跨域請求了

反向代理

反向代理一般是用來做負載均衡的

當我請求一個伺服器的時候,其實請求的是伺服器端設定的代理伺服器

由代理伺服器把若幹大量的請求分發給不同的伺服器進行處理

再由伺服器把響應給到代理伺服器

代理伺服器傳回給用戶端

封裝 AJAX

ajax 使用起來太麻煩,因為每次都要寫很多的代碼

那麼我們就封裝一個 ajax 方法來讓我們使用起來簡單一些

确定一下使用的方式

因為有一些内容可以不傳遞,我們可以使用預設值,是以選擇對象傳遞參數的方式

// 使用的時候直接調用,傳遞一個對象就可以

ajax({

url: '', // 請求的位址

type: '', // 請求方式

async: '', // 是否異步

data: '', // 攜帶的參數

dataType: '', // 要不要執行 json.parse

success: function () {} // 成功以後執行的函數

})

确定好使用方式以後,就開始書寫封裝函數

封裝

function ajax(options) {

// 先準備一個預設值 var defInfo = {

url: '', // 位址不需要預設值    type: 'GET', // 請求方式的預設值是 GET    async: false, // 預設值是異步    data: '', // 參數沒有預設值    dataType: 'string', // 預設不需要執行 json.parse    success () {}, // 預設是一個函數  }​           

// 先來判斷一下有沒有傳遞 url,如果沒有,直接抛出異常 if (!options.url) {

throw new Error('url 必須傳遞')           

}​

// 有了 url 以後就,我們就把使用者傳遞的參數和我們的預設資料合并 for (let key in options) {

defInfo[key] = options[key]           

// 接下來的一切我們都是使用我們的 defInfo 就可以了 // 第一步就是判斷參數 data // data 可以不傳遞,可以為空 // data 也可以是一個 key=value&key=value 格式的字元串 // data 也可以是一個對象 // 否則就抛出異常 if (!(typeof defInfo.data === 'string' && /^(w+=w+&?)*$/.test(defInfo.data) || Object.prototype.toString.call(defInfo.data) === '[object Object]')) {

throw new Error('請按照要求傳遞參數')           

// 參數處理完畢以後,在判斷 async 的資料類型 // 隻能傳遞 布爾資料類型 if (typeof defInfo.async !== 'boolean') {

throw new Error('async 參數隻接受布爾資料類型')           

// 在接下來就判斷 type // 請求方式我們隻接受 GET 或着 POST if (!(defInfo.type.toUpperCase() === 'GET' || defInfo.type.toUpperCase() === 'POST')) {

throw new Error('目前本插件隻接受 GET 和 POST 方式,請期待更新')           

// 接下來就是判斷 success 的判斷,必須是一個函數 if (Object.prototype.toString.call(defInfo.success) !== '[object Function]') {

throw new Error('success 隻接受函數資料類型')           

// 參數都沒有問題了 // 我們就要把 data 處理一下了 // 因為 data 有可能是對象,當 data 是一個對象的時候,我們要把它轉換成一個字元串 var str = ''

if (Object.prototype.toString.call(defInfo.data) === '[object Object]') {

for (let attr in defInfo.data) {
  str += `${attr}=${defInfo.data[attr]}&`
}
str = str.slice(0, -1)
defInfo.data = str           

// 參數全部驗證過了以後,我們就可以開始進行正常的 ajax 請求了 // 1. 準備一個 ajax 對象 // 因為要處理相容問題,是以我們準備一個函數 function createXHR() {

if (XMLHttpRequest) {
  return new XMLHttpRequest()
} else {
  return new ActiveXObject('Microsoft.XMLHTTP')
}           

// 2. 建立一個 ajax 對象 var xhr = createXHR()​

// 3. 進行 open xhr.open(defInfo.type, defInfo.url + (defInfo.type.toUpperCase() === 'GET' ?

?${defInfo.data}&_=${new Date().getTime()}

: ''), defInfo.async)​

if (defInfo.type.toUpperCase() === 'POST') {

xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')           

// 4. 進行 send xhr.send((defInfo.type.toUpperCase() === 'POST' ?

${defInfo.data}

: ''))​

// 5. 接受響應 xhr.onreadystatechange = function () {

if (xhr.readyState === 4 && /2\d{2}/.test(xhr.status)) {
  // 表示成功,我們就要執行 success      // 但是要進行 dataType 的判斷      if (defInfo.dataType === 'json') {
    defInfo.success(JSON.parse(xhr.responseText))
  } else {
    defInfo.success()
  }
}           

}}

繼續閱讀