封裝Ajax函數(shù)

要實(shí)現(xiàn)的效果

image.png

定義options參數(shù)選項(xiàng)

itheima() 函數(shù)是我們自定義的 Ajax 函數(shù)羞海,它接收一個(gè)配置對(duì)象作為參數(shù),配置對(duì)象中可以配置如下屬性:

  • method 請(qǐng)求的類(lèi)型
  • url 請(qǐng)求的 URL 地址
  • data 請(qǐng)求攜帶的數(shù)據(jù)
  • success 請(qǐng)求成功之后的回調(diào)函數(shù)

處理data參數(shù)

需要把 data 對(duì)象曲管,轉(zhuǎn)化成查詢(xún)字符串的格式却邓,從而提交給服務(wù)器,因此提前定義 resolveData 函數(shù)如下:

/*** 處理 data 參數(shù)
* @param {data} 需要發(fā)送到服務(wù)器的數(shù)據(jù)
* @returns {string} 返回拼接好的查詢(xún)字符串 name=zs&age=10
*/
function resolveData(data) {
  var arr = []
  for (var k in data) {
    var str = k + '=' + data[k]
    arr.push(str)
  }

  return arr.join('&')
}

定義itheima函數(shù)

在 itheima() 函數(shù)中院水,需要?jiǎng)?chuàng)建 xhr 對(duì)象腊徙,并監(jiān)聽(tīng) onreadystatechange 事件:

function itheima(options) {
  var xhr = new XMLHttpRequest()

  // 把外界傳遞過(guò)來(lái)的參數(shù)對(duì)象,轉(zhuǎn)換為 查詢(xún)字符串
  var qs = resolveData(options.data)
  // 注冊(cè)監(jiān)聽(tīng)
  xhr.onreadystatechange = function () {
  // 注冊(cè)監(jiān)聽(tīng)
    if (xhr.readyState === 4 && xhr.status === 200) {
      // 把服務(wù)器的json字符串轉(zhuǎn)成js對(duì)象
      var result = JSON.parse(xhr.responseText)
      options.success(result)
    }
  }
}

判斷請(qǐng)求的類(lèi)型

不同的請(qǐng)求類(lèi)型檬某,對(duì)應(yīng) xhr 對(duì)象的不同操作撬腾,因此需要對(duì)請(qǐng)求類(lèi)型進(jìn)行 if … else … 的判斷:

if (options.method.toUpperCase() === 'GET') {
  // 發(fā)起GET請(qǐng)求
  xhr.open(options.method, options.url + '?' + qs)
  xhr.send()
} else if (options.method.toUpperCase() === 'POST') {
  // 發(fā)起POST請(qǐng)求
  xhr.open(options.method, options.url)
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
  xhr.send(qs)
}

XMLHttpRequest Level2的新特性

舊版XMLHttpRequest的缺點(diǎn)

  • 只支持文本數(shù)據(jù)的傳輸,無(wú)法用來(lái)讀取和上傳文件
  • 傳送和接收數(shù)據(jù)時(shí)恢恼,沒(méi)有進(jìn)度信息民傻,只能提示有沒(méi)有完成

XMLHttpRequest Level2的新功能

  • 可以設(shè)置 HTTP 請(qǐng)求的時(shí)限
  • 可以使用 FormData 對(duì)象管理表單數(shù)據(jù)
  • 可以上傳文件
  • 可以獲得數(shù)據(jù)傳輸?shù)倪M(jìn)度信息

設(shè)置HTTP請(qǐng)求時(shí)限

有時(shí),Ajax 操作很耗時(shí)场斑,而且無(wú)法預(yù)知要花多少時(shí)間漓踢。如果網(wǎng)速很慢,用戶(hù)可能要等很久漏隐。新版本的 XMLHttpRequest 對(duì)象喧半,增加了 timeout 屬性,可以設(shè)置 HTTP 請(qǐng)求的時(shí)限:


image.png

上面的語(yǔ)句青责,將最長(zhǎng)等待時(shí)間設(shè)為 3000 毫秒挺据。過(guò)了這個(gè)時(shí)限取具,就自動(dòng)停止HTTP請(qǐng)求。與之配套的還有一個(gè)timeout` 事件吴菠,用來(lái)指定回調(diào)函數(shù):


image.png
<script>
  var xhr = new XMLHttpRequest()
  // 設(shè)置 超時(shí)時(shí)間
  xhr.timeout = 30
  // 設(shè)置超時(shí)以后的處理函數(shù)
  xhr.ontimeout = function () {
    console.log('請(qǐng)求超時(shí)了者填!')
  }
  xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
  xhr.send()
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
      console.log(xhr.responseText)
    }
  }
</script>

FormData對(duì)象管理表單數(shù)據(jù)

Ajax 操作往往用來(lái)提交表單數(shù)據(jù)。為了方便表單處理做葵,HTML5 新增了一個(gè) FormData 對(duì)象占哟,可以模擬表單操作:

 // 1. 新建 FormData 對(duì)象
 var fd = new FormData()
 // 2. 為 FormData 添加表單項(xiàng)
 fd.append('uname', 'zs')
 fd.append('upwd', '123456')
 // 3. 創(chuàng)建 XHR 對(duì)象
 var xhr = new XMLHttpRequest()
 // 4. 指定請(qǐng)求類(lèi)型與URL地址
 xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
 // 5. 直接提交 FormData 對(duì)象,這與提交網(wǎng)頁(yè)表單的效果酿矢,完全一樣
 xhr.send(fd)

FormData對(duì)象管理表單數(shù)據(jù)

FormData對(duì)象也可以用來(lái)獲取網(wǎng)頁(yè)表單的值榨乎,示例代碼如下:

// 獲取表單元素
var form = document.querySelector('#form1')
// 監(jiān)聽(tīng)表單元素的 submit 事件
form.addEventListener('submit', function(e) {
 e.preventDefault()
 // 根據(jù) form 表單創(chuàng)建 FormData 對(duì)象,會(huì)自動(dòng)將表單數(shù)據(jù)填充到 FormData 對(duì)象中
 var fd = new FormData(form)
 var xhr = new XMLHttpRequest()
 xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
 xhr.send(fd)
 xhr.onreadystatechange = function() {}
})

上傳文件

新版 XMLHttpRequest 對(duì)象瘫筐,不僅可以發(fā)送文本信息蜜暑,還可以上傳文件。

實(shí)現(xiàn)步驟:

① 定義 UI 結(jié)構(gòu)
② 驗(yàn)證是否選擇了文件
③ 向 FormData 中追加文件
④ 使用 xhr 發(fā)起上傳文件的請(qǐng)求
⑤ 監(jiān)聽(tīng) onreadystatechange 事件

定義UI結(jié)構(gòu)

 <!-- 1. 文件選擇框 -->
 <input type="file" id="file1" />
 <!-- 2. 上傳按鈕 -->
 <button id="btnUpload">上傳文件</button>
 <br />
 <!-- 3. 顯示上傳到服務(wù)器上的圖片 -->
 <img src="" alt="" id="img" width="800" />

驗(yàn)證是否選擇了文件

// 1. 獲取上傳文件的按鈕
var btnUpload = document.querySelector('#btnUpload')
// 2. 為按鈕添加 click 事件監(jiān)聽(tīng)
btnUpload.addEventListener('click', function() {
 // 3. 獲取到選擇的文件列表
 var files = document.querySelector('#file1').files
 if (files.length <= 0) {
 return alert('請(qǐng)選擇要上傳的文件策肝!')
 }
 // ...后續(xù)業(yè)務(wù)邏輯
})

向FormData中追加文件

// 1. 創(chuàng)建 FormData 對(duì)象
var fd = new FormData()
// 2. 向 FormData 中追加文件
fd.append('avatar', files[0])

使用 xhr 發(fā)起上傳文件的請(qǐng)求

// 1. 創(chuàng)建 xhr 對(duì)象
var xhr = new XMLHttpRequest()
// 2. 調(diào)用 open 函數(shù)肛捍,指定請(qǐng)求類(lèi)型與URL地址。其中之众,請(qǐng)求類(lèi)型必須為 POST
xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar')
// 3. 發(fā)起請(qǐng)求
xhr.send(fd)

監(jiān)聽(tīng)onreadystatechange事件

xhr.onreadystatechange = function() {
 if (xhr.readyState === 4 && xhr.status === 200) {
     var data = JSON.parse(xhr.responseText)
     if (data.status === 200) { // 上傳文件成功
     // 將服務(wù)器返回的圖片地址拙毫,設(shè)置為 <img> 標(biāo)簽的 src 屬性
        document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
     } else { // 上傳文件失敗
         console.log(data.message)
     }
 }
}

顯示文件上傳進(jìn)度

計(jì)算文件上傳進(jìn)度

新版本的 XMLHttpRequest 對(duì)象中,可以通過(guò)監(jiān)聽(tīng) xhr.upload.onprogress 事件棺禾,來(lái)獲取到文件的上傳進(jìn)度缀蹄。語(yǔ)法格式如下:

// 創(chuàng)建 XHR 對(duì)象
var xhr = new XMLHttpRequest()
// 監(jiān)聽(tīng) xhr.upload 的 onprogress 事件
xhr.upload.onprogress = function(e) {
     // e.lengthComputable 是一個(gè)布爾值,表示當(dāng)前上傳的資源是否具有可計(jì)算的長(zhǎng)度
     if (e.lengthComputable) {
         // e.loaded 已傳輸?shù)淖止?jié)
         // e.total 需傳輸?shù)目傋止?jié)
         var percentComplete = Math.ceil((e.loaded / e.total) * 100)
     }
 }

導(dǎo)入需要的庫(kù)

<link rel="stylesheet" href="./lib/bootstrap.css" />
<script src="./lib/jquery.js"></script>

基于Bootstrap渲染進(jìn)度條

 <!-- 進(jìn)度條 -->
 <div class="progress" style="width: 500px; margin: 10px 0;">
     <div class="progress-bar progress-bar-info progress-bar?striped active" id="percent" style="width: 0%">
     0%
     </div>
 </div>

動(dòng)態(tài)設(shè)置到進(jìn)度條上

xhr.upload.onprogress = function(e) {
     if (e.lengthComputable) {
         // 1. 計(jì)算出當(dāng)前上傳進(jìn)度的百分比
         var percentComplete = Math.ceil((e.loaded / e.total) * 100)
         $('#percent')
         // 2. 設(shè)置進(jìn)度條的寬度
         .attr('style', 'width:' + percentComplete + '%')
         // 3. 顯示當(dāng)前的上傳進(jìn)度百分比
         .html(percentComplete + '%')
     }
}

監(jiān)聽(tīng)上傳完成的事件

xhr.upload.onload = function() {
     $('#percent')
     // 移除上傳中的類(lèi)樣式
     .removeClass()
     // 添加上傳完成的類(lèi)樣式
     .addClass('progress-bar progress-bar-success')
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末膘婶,一起剝皮案震驚了整個(gè)濱河市缺前,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悬襟,老刑警劉巖衅码,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異古胆,居然都是意外死亡肆良,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)逸绎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人夭谤,你說(shuō)我怎么就攤上這事棺牧。” “怎么了朗儒?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵参淹,是天一觀的道長(zhǎng)浙值。 經(jīng)常有香客問(wèn)我开呐,道長(zhǎng),這世上最難降的妖魔是什么瓦戚? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮印衔,結(jié)果婚禮上当编,老公的妹妹穿的比我還像新娘徒溪。我一直安慰自己鲤桥,他們只是感情好茶凳,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著箱沦,像睡著了一般灶伊。 火紅的嫁衣襯著肌膚如雪聘萨。 梳的紋絲不亂的頭發(fā)上米辐,一...
    開(kāi)封第一講書(shū)人閱讀 50,021評(píng)論 1 291
  • 那天征冷,我揣著相機(jī)與錄音肴捉,去河邊找鬼齿穗。 笑死窃页,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的复濒。 我是一名探鬼主播脖卖,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼巧颈!你這毒婦竟也來(lái)了畦木?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤砸泛,失蹤者是張志新(化名)和其女友劉穎十籍,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體唇礁,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡勾栗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了盏筐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片械姻。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖机断,靈堂內(nèi)的尸體忽然破棺而出楷拳,到底是詐尸還是另有隱情,我是刑警寧澤吏奸,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布欢揖,位于F島的核電站,受9級(jí)特大地震影響奋蔚,放射性物質(zhì)發(fā)生泄漏她混。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一泊碑、第九天 我趴在偏房一處隱蔽的房頂上張望坤按。 院中可真熱鬧,春花似錦馒过、人聲如沸臭脓。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)来累。三九已至,卻和暖如春窘奏,著一層夾襖步出監(jiān)牢的瞬間嘹锁,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工着裹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留领猾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓骇扇,卻偏偏與公主長(zhǎng)得像摔竿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子匠题,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 1.簡(jiǎn)介 瀏覽器與服務(wù)器之間拯坟,采用 HTTP 協(xié)議通信。用戶(hù)在瀏覽器地址欄鍵入一個(gè)網(wǎng)址韭山,或者通過(guò)網(wǎng)頁(yè)表單向服務(wù)器提...
    wit92閱讀 339評(píng)論 0 0
  • 瀏覽器與服務(wù)器之間郁季,采用HTTP協(xié)議通信。用戶(hù)在瀏覽器地址欄鍵入一個(gè)網(wǎng)址钱磅,或者通過(guò)網(wǎng)頁(yè)表單向服務(wù)器提交內(nèi)容橘原,這時(shí)瀏...
    許先生__閱讀 494評(píng)論 1 2
  • 一,1個(gè)HTTP請(qǐng)求一般由四部分組成: (1)GET請(qǐng)求:一般用于信息獲取a.使用URL傳遞參數(shù)b.對(duì)所發(fā)送信息的...
    Leisure_blogs閱讀 274評(píng)論 0 0
  • 摘要 一戈抄、老版本的XMLHttpRequest對(duì)象二狡相、老版本的缺點(diǎn)三、 新版本的功能介紹四褪迟、HTTP請(qǐng)求的實(shí)現(xiàn)五冗恨、...
    silly鴻閱讀 735評(píng)論 0 0
  • 今天感恩節(jié)哎答憔,感謝一直在我身邊的親朋好友。感恩相遇掀抹!感恩不離不棄虐拓。 中午開(kāi)了第一次的黨會(huì),身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,559評(píng)論 0 11