進(jìn)階12 ajax實(shí)踐

1. ajax 是什么?有什么作用苔咪?

Ajax(['eid??ks])是Asynchronous JavaScript and XML的縮寫(xiě)锰悼,從標(biāo)題里就能看出,是異步的JS和XML团赏,這一技術(shù)能夠向服務(wù)器請(qǐng)求額外的數(shù)據(jù)而無(wú)需卸載整個(gè)頁(yè)面箕般,會(huì)帶來(lái)良好的用戶(hù)體驗(yàn)。因?yàn)閭鹘y(tǒng)的HTTP 請(qǐng)求流程大概如下:

  1. 瀏覽器向服務(wù)器發(fā)送請(qǐng)求
  2. 服務(wù)器根據(jù)瀏覽器傳來(lái)數(shù)據(jù)生成response
  3. 服務(wù)器把response返回給瀏覽器
  4. 瀏覽器刷新整個(gè)頁(yè)面顯示最新數(shù)據(jù)

這個(gè)過(guò)程是同步的舔清,順序執(zhí)行丝里。如果網(wǎng)絡(luò)傳輸速率過(guò)慢或者其他情況導(dǎo)致,用戶(hù)長(zhǎng)時(shí)間等待請(qǐng)求結(jié)果体谒,而瀏覽器是卡死狀態(tài)杯聚,那么體驗(yàn)就很糟糕。

另外如果當(dāng)前頁(yè)面DOM結(jié)構(gòu)特別復(fù)雜抒痒,內(nèi)容繁多幌绍,而需要請(qǐng)求的僅僅是一小段數(shù)據(jù),卻要大費(fèi)周章故响,數(shù)據(jù)到來(lái)后總是要重新渲染頁(yè)面傀广。

而使用AJAX技術(shù),通過(guò)JavaScript操作瀏覽器提供的XMLHttpRequest 對(duì)象彩届,去發(fā)送一個(gè)Ajax請(qǐng)求伪冰,并接收服務(wù)器傳來(lái)的數(shù)據(jù),然后操作DOM將新數(shù)據(jù)對(duì)網(wǎng)頁(yè)的某部分進(jìn)行更新惨缆,使用Ajax最直觀(guān)的感受是向服務(wù)器獲取新數(shù)據(jù)不需要刷新頁(yè)面等待了糜值。

2. 前后端開(kāi)發(fā)聯(lián)調(diào)需要注意哪些事情丰捷?后端接口完成前如何 mock 數(shù)據(jù)?

  • 前后端聯(lián)調(diào)時(shí)需要溝通定義接口:

  1. 約定好請(qǐng)求方法
  2. 請(qǐng)求路徑(URL)
  3. 前端需要傳遞什么樣的參數(shù)(入?yún)ⅲ?/li>
  4. 數(shù)據(jù)格式(回參寂汇,包括可能的狀態(tài)碼)
  • mock數(shù)據(jù):

在后端接口完成之前病往,前端通過(guò)mock數(shù)據(jù),能夠在不依賴(lài)后端環(huán)境的情況下進(jìn)行開(kāi)發(fā)骄瓣,只要約定好接口停巷。

常用的手段就是搭建本地mock server,如果裝了nodejs榕栏,就可以用npm 下載安裝了畔勤,然后只需要在本地的mock server中實(shí)現(xiàn)請(qǐng)求路由映射即可,如果使用js語(yǔ)言扒磁,也就是 router.js庆揪,可以按照約定在里面模擬假數(shù)據(jù),以相應(yīng)前端瀏覽器的請(qǐng)求妨托。

除此之外缸榛,還可以使用線(xiàn)上的模擬數(shù)據(jù)生成服務(wù),比如Easy Mock:
http://www.easy-mock.com 注冊(cè) 打開(kāi)任意一個(gè)項(xiàng)目 創(chuàng)建接口 使用接口(AJAX兰伤、JSONP都行内颗,具體看文檔)
xhr.open('get', 'http://www.easy-mock.com/mock/59b95cf3e0dc663341a8fa20/example/loadMore', true)

3. 點(diǎn)擊按鈕,使用 ajax 獲取數(shù)據(jù)敦腔,如何在數(shù)據(jù)到來(lái)之前防止重復(fù)點(diǎn)擊?

首先這樣做的目的均澳,是因?yàn)樵谡鎸?shí)的網(wǎng)絡(luò)環(huán)境中,傳輸速率必然是沒(méi)有用戶(hù)鼠標(biāo)雙擊按鈕更快符衔,在當(dāng)前請(qǐng)求未到來(lái)之前找前,用戶(hù)的習(xí)慣總愛(ài)再次點(diǎn)擊按鈕,這會(huì)導(dǎo)致瀏覽器重復(fù)發(fā)送請(qǐng)求判族,結(jié)果對(duì)于用戶(hù)來(lái)說(shuō)纸厉,占用更多帶寬資源還好說(shuō),如果是網(wǎng)購(gòu)付款按鈕呢五嫂,另外對(duì)于服務(wù)器端來(lái)說(shuō)颗品,也會(huì)帶來(lái)更大的運(yùn)行壓力。

一個(gè)典型的例子就是上大學(xué)的時(shí)候沃缘,到了選修課端口開(kāi)放的時(shí)候躯枢,大家齊刷刷早起守著電腦,不停的刷新槐臀,結(jié)果平時(shí)很流暢的教務(wù)網(wǎng)站锄蹂,到了選(搶?zhuān)┱n的時(shí)候,變得異乘卡頓得糜,F(xiàn)5都磨爛了敬扛,也刷新不出來(lái)。其實(shí)這個(gè)時(shí)候服務(wù)器內(nèi)心是崩潰的朝抖。

回到正題啥箭,阻止用戶(hù)重復(fù)點(diǎn)擊,一個(gè)簡(jiǎn)單的做法是治宣,令用戶(hù)的點(diǎn)擊變得無(wú)效急侥, 使用狀態(tài)鎖,請(qǐng)求未處理完成之前侮邀,拒絕再次請(qǐng)求坏怪,而請(qǐng)求到了并處理完之后,恢復(fù)到可請(qǐng)求狀態(tài)绊茧。

具體的代碼演示铝宵,在下文中,將會(huì)提到华畏。

4. 實(shí)現(xiàn)加載更多的功能捉超,后端在本地使用server-mock來(lái)模擬數(shù)據(jù)

本地模擬成功:


代碼地址,注意唯绍!想要看到效果,需要把 index.html 和 router.js 分別保存在同一個(gè)文件夾下枝誊,然后終端里使用server mock 開(kāi)啟mock况芒。

5. 對(duì)AJAX進(jìn)行封裝,這是必須的(以get為例)

var btn = document.querySelector('#load-more')
    var ct = document.querySelector('#ct')
    var pageIndex = 0
    var isDataArrive = true //設(shè)計(jì)個(gè)狀態(tài)鎖

    btn.addEventListener('click', function(e){
      e.preventDefault() //防止點(diǎn)擊 a 鏈接頁(yè)面跳到頂部 或者h(yuǎn)ref里 javascript:void(0)
      if(!isDataArrive){ // 1. 點(diǎn)擊按鈕后叶撒,一開(kāi)始先判斷绝骚,如果狀態(tài)是false,數(shù)據(jù)還沒(méi)到來(lái)祠够,就直接忽略
        return;
      }
      loadData(function(news){  //loadData(renderPage) // 執(zhí)行l(wèi)oadData時(shí)压汪,數(shù)據(jù)到了,執(zhí)行callback古瓤,也就是傳入的函數(shù) renderPage
        renderPage(news)
        pageIndex += 5
        isDataArrive = true
      })
      isDataArrive = false
    })

    function loadData(callback){
      ajax({
        type: 'get',
        url: 'loadMore',
        data: {
          index: pageIndex,
          length: 5 
        },
        onSuccess: callback,
        onError: function(){
          console.log('error')
        }
      })
    }

    function renderPage(news){
      var fragment = document.createDocumentFragment() 
      for( var i = 0; i < news.length; i++){
        var node = document.createElement('li')
        node.innerText = news[i]
        fragment.appendChild(node)
      }
      ct.appendChild(fragment)
    }

    function ajax(options){
      var xhr = new XMLHttpRequest()
      xhr.onreadystatechange = function(){
        if(xhr.readyState === 4){
          if(xhr.status === 200 || xhr.status === 304){
            var results = JSON.parse(xhr.responseText) 
            options.onSuccess(results) //相當(dāng)于callback(results)
          }else{
          options.onError()
          }
        }
      }
      var query = '?'
      for(key in options.data){
        query += key + '=' + options.data[key] + '&'
      }
      query = query.substr(0, query.length-1) //舍去最后一個(gè)&止剖,截取出來(lái)
      xhr.open(options.type, options.url + query, true)
      if(type === 'post'){
        xhr.send(dataStr)
      }else{
        xhr.send()
      }
  }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市落君,隨后出現(xiàn)的幾起案子穿香,更是在濱河造成了極大的恐慌,老刑警劉巖绎速,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件皮获,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡纹冤,警方通過(guò)查閱死者的電腦和手機(jī)洒宝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)购公,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人雁歌,你說(shuō)我怎么就攤上這事宏浩。” “怎么了将宪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵绘闷,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我较坛,道長(zhǎng)印蔗,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任丑勤,我火速辦了婚禮华嘹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘法竞。我一直安慰自己耙厚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布岔霸。 她就那樣靜靜地躺著薛躬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪呆细。 梳的紋絲不亂的頭發(fā)上型宝,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音絮爷,去河邊找鬼趴酣。 笑死,一個(gè)胖子當(dāng)著我的面吹牛坑夯,可吹牛的內(nèi)容都是我干的岖寞。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼柜蜈,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼仗谆!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起淑履,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤胸私,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后鳖谈,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體岁疼,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捷绒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瑰排。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖暖侨,靈堂內(nèi)的尸體忽然破棺而出椭住,到底是詐尸還是另有隱情,我是刑警寧澤字逗,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布京郑,位于F島的核電站,受9級(jí)特大地震影響葫掉,放射性物質(zhì)發(fā)生泄漏些举。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一俭厚、第九天 我趴在偏房一處隱蔽的房頂上張望户魏。 院中可真熱鬧,春花似錦挪挤、人聲如沸叼丑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鸠信。三九已至,卻和暖如春论寨,著一層夾襖步出監(jiān)牢的瞬間星立,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工政基, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人闹啦。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓沮明,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親窍奋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子荐健,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

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