主頁 > 知識(shí)庫 > 基于h5的history改善ajax列表請(qǐng)求體驗(yàn)

基于h5的history改善ajax列表請(qǐng)求體驗(yàn)

熱門標(biāo)簽:越南河內(nèi)地圖標(biāo)注 個(gè)人怎樣在百度地圖標(biāo)注地名 機(jī)器人電銷騙局揭秘 ai機(jī)器人電銷資源 云呼外撥網(wǎng)絡(luò)電話系統(tǒng) 硅語電話機(jī)器人公司 騰訊地圖標(biāo)注位置能用多久 地圖標(biāo)注項(xiàng)目怎么樣 超級(jí)大富翁地圖標(biāo)注

信息比較豐富的網(wǎng)站通常會(huì)以分頁顯示,在點(diǎn)“下一頁”時(shí),很多網(wǎng)站都采用了動(dòng)態(tài)請(qǐng)求的方式,避免頁面刷新。雖然大家都是ajax,但是從一些小的細(xì)節(jié)還是 可以區(qū)分優(yōu)劣。一個(gè)小的細(xì)節(jié)是能否支持瀏覽器“后退”和“前進(jìn)“鍵。本文討論兩種方法,讓瀏覽器可以后退和前進(jìn),或者說讓ajax就像重定向到新頁面一樣 擁有能夠返回到上一頁或者前進(jìn)到下一頁。

      數(shù)據(jù)實(shí)現(xiàn)分頁顯示,最簡(jiǎn)單的做法是在網(wǎng)址后面加多個(gè)page的當(dāng)數(shù),點(diǎn)“下一頁”時(shí),讓網(wǎng)頁重定向到page+1的新地址。例如新浪的新聞網(wǎng)就 是這么做的,通過改變網(wǎng)址實(shí)現(xiàn):index_1、index_2、index_3……。但是如果這個(gè)列表并不是頁面的主體部分,或者頁面的其它部分有很多 圖片等豐富元素,例如導(dǎo)航是一個(gè)很大的slider,再使用這樣的方式,整個(gè)頁面會(huì)閃爍得厲害,并且很多資源得重新加載。所以使用ajax請(qǐng)求,動(dòng)態(tài)改變 DOM。

      但是普通的動(dòng)態(tài)的請(qǐng)求不會(huì)使網(wǎng)址發(fā)生變化,用戶點(diǎn)了下一頁,或者點(diǎn)了第幾頁,想要返回到上一個(gè)頁面時(shí),可能會(huì)去點(diǎn)瀏覽器的返回鍵,這樣就導(dǎo)致返回的時(shí)候不是返回到原先查看的頁面了,而是上一個(gè)網(wǎng)址了。例如央視的新聞網(wǎng)就是這樣的。下面從ajax請(qǐng)求開始說起,以一個(gè)完整的案例進(jìn)行分析。

      做了一個(gè)demo

   首先,寫一個(gè)請(qǐng)求:

 //當(dāng)前第幾頁
  var pageIndex = 0;
  //請(qǐng)求函數(shù)
  function makeRequest(pageIndex){
    var request = new XMLHttpRequest();
    request.onreadystatechange = stateChange;
    //請(qǐng)求傳兩個(gè)參數(shù),一個(gè)是當(dāng)前第幾頁,另一個(gè)是每頁的數(shù)據(jù)條數(shù)
    request.open("GET", "/getBook?page=" + pageIndex + "limit=4", true);
    request.send(null);
    function stateChange(){
      //狀態(tài)碼為4,表示loaded,請(qǐng)求完成
      if(request.readyState !== 4 ){
        return;
      }
      //請(qǐng)求成功
      if(request.status >= 200  request.status  300 || request.status === 304){
        var books = JSON.parse(request.responseText);
        renderPage(books); 
      }
    }
  }

     拿到數(shù)據(jù)后進(jìn)行渲染:

  function renderPage(books){
    var bookHtml = 
      "table>" +
      "  tr>" +
      "    th>書名/th>" +
      "    th>作者/th>" +
      "    th>版本/th>" +
      "  /tr>";
    for(var i in books){
      bookHtml += 
        "tr>" +
        "  td>" + books[i].book_name + "/td>" +
        "  td>" + books[i].author + "/td>" +
        "  td>" + books[i].edition + "/td>" +
        "/tr>";
    }
    bookHtml += "/table>";
    bookHtml += 
      "button>上一頁/button>" + 
      "button onclick='nextPage();'>下一頁/button>";
    var section = document.createElement("section");
    section.innerHtml = bookHtml;
    document.getElementById("book").appendChild(section); 
  }

這樣一個(gè)基本的ajax請(qǐng)求就搭起來了,然后再響應(yīng)“下一頁”按鈕:

  function nextPage(){
    //將頁面的index加1
    pageIndex++;
    //重新發(fā)請(qǐng)求和頁面加載
    makeRequest(pageIndex);
  }

到此,如果不做任何處理的話,就不能夠發(fā)揮瀏覽器返回、前進(jìn)按鈕的作用。

      如果能夠檢測(cè)用戶點(diǎn)了后退、前進(jìn)按鈕的話,就可以做些文章。h5就是增加了這么一個(gè)事件window.onpopstate,當(dāng)用戶點(diǎn)擊那兩個(gè)按鈕就會(huì)觸 發(fā)這個(gè)事件。但是光檢測(cè)到這個(gè)事件是不夠的,還得能夠傳些參數(shù),也就是說返回到之前那個(gè)頁面的時(shí)候得知道那個(gè)頁面的pageIndex。通過 history的pushState方法可以達(dá)到這個(gè)目的,pushState(pageIndex)將當(dāng)前頁的pageIndex存起來,再返回到這個(gè) 頁面時(shí)獲取到這個(gè)pageIndex。pushState的參數(shù)如下:

復(fù)制代碼 代碼如下:

window.history.pushState(state, title, url);

      其中state為一個(gè)object{},用來存放當(dāng)前頁面的數(shù)據(jù),title標(biāo)題沒有多大的作用,url為當(dāng)前頁面的url,一旦更改了這個(gè)url,瀏覽器地址欄的地址也會(huì)跟著變化。

      于是,在請(qǐng)求下一頁數(shù)據(jù)的nextPage函數(shù)里面,加多一步操作:

  function nextPage(){
    pageIndex++;
    makeRequest(pageIndex);
    //存放當(dāng)前頁面的數(shù)據(jù)
    window.history.pushState({page: pageIndex}, null, window.location.href); 
  }

然后監(jiān)聽popstate事件:

  //如果用戶點(diǎn)擊返回或者前進(jìn)按鈕
  window.addEventListener("popstate", function(event){
    var page = 0;
    //由于第一頁沒有pushState,所以返回到第一頁的時(shí)候是沒有數(shù)據(jù)的,因此得做下判斷
    if(event.state !== null){
      page = event.state.page;
    }
    makeRequest(page); 
    pageIndex = page;
  });

     state數(shù)據(jù)通過event傳進(jìn)來,這樣就可以得到pageIndex。


但是,這樣實(shí)現(xiàn)還有問題,在第二頁的時(shí)候如果刷新頁面的話,會(huì)發(fā)生錯(cuò)亂,如下所示:首先點(diǎn)下一頁到第二頁,然后刷新頁面,出現(xiàn)第一頁,再點(diǎn)下一頁,出現(xiàn)第二頁,點(diǎn)返回時(shí)出現(xiàn)問題,顯示還是第二頁,不是期望的第一頁,直到再次點(diǎn)返回時(shí)才是第一頁:

 從右邊的工具欄可以發(fā)現(xiàn),點(diǎn)第一次返回的時(shí)候獲取到的pageIndex仍然是1。對(duì)于這種情況,需要分析history模型,如下所示:

 可以理解為對(duì)history的操作,瀏覽器有一個(gè)隊(duì)列,用來存放訪問的記錄,包括每個(gè)訪問的網(wǎng)址還有state數(shù)據(jù)。一開始,隊(duì)列的首指針指向page = 0的位置,點(diǎn)下一頁時(shí),執(zhí)行了pushState,在這個(gè)隊(duì)列插入了一個(gè)元素,同時(shí)通過pushState操作記錄了這個(gè)元素的url和state數(shù)據(jù)。 在這里可以看出,pushState的操作最重要的作用還是給history隊(duì)列插入元素,這樣瀏覽器的后退按鈕才不是置灰的狀態(tài),其次才是上面說的存放 數(shù)據(jù)。點(diǎn)后退的時(shí)候,隊(duì)首指針后退一步指向page = 0的位置,點(diǎn)前進(jìn)時(shí)又前進(jìn)指向page = 1的位置。

如果在page = 1的位置刷新頁面,模型是這個(gè)樣子的:

在第2步刷新的時(shí)候,頁面的pageIndex又恢復(fù)成默認(rèn)值0,所以page = 0,顯示第一頁數(shù)據(jù),但是history所用的隊(duì)列并沒有改變。然后再點(diǎn)下一頁時(shí),又給這個(gè)隊(duì)列push了一個(gè)元素,這個(gè)隊(duì)列就有兩個(gè)pageIndex 為1的元素,所以必須得兩次返回才能回到page = 0的位置,也就是上面說的錯(cuò)亂的情況。

根據(jù)上面的分析,這樣的實(shí)現(xiàn)是有問題的,一但用戶不是在page = 0的位置刷新頁面,就會(huì)出現(xiàn)需要點(diǎn)多次返回按鈕才能夠回到原先的頁面。

所以得在刷新的時(shí)候,把當(dāng)前頁的state數(shù)據(jù)更新一下,用replaceState,替換隊(duì)列隊(duì)首指針的數(shù)據(jù),也就是當(dāng)前頁的數(shù)據(jù)。方法是頁面初始化時(shí)replace一下:

window.history.replaceState({page: pageIndex /*此處為0*/}, null, window.location.href);
這樣模型就變成:

但其實(shí)用戶刷新的時(shí)候更希望的是還是顯示當(dāng)前頁,而不是回到第一頁。一個(gè)解決辦法是用當(dāng)前頁的window.history.state數(shù)據(jù),這個(gè)屬性瀏覽器支持得比較晚。在頁面初始化時(shí)設(shè)置pageIndex時(shí)就從history.state?。?/p>

 

var pageIndex = window.history.state === null ? 0 : window.history.state.page; 

      safari里面的history.state是最近執(zhí)行pushState傳入的數(shù)據(jù),因此這個(gè)辦法在chrome/firefox里面行得通,但是safari行不通。

      第二種辦法是借助h5的localStorage存放當(dāng)前頁數(shù):

 //頁面初始化,取當(dāng)前第幾頁先從localStorage取
  var pageIndex = window.localStorage.pageIndex || 0;

  function nextPage(){
    //將頁面的index加1,同時(shí)存放在localStorage
    window.localStorage.pageIndex = ++pageIndex;
    //重新發(fā)請(qǐng)求和頁面加載
    makeRequest(pageIndex);
    window.history.pushState({page: pageIndex}, null, window.location.href); 
  }

  window.addEventListener("popstate", function(event){
    var page = 0;
    if(event.state !== null){
      page = event.state.page;
    }
    makeRequest(page); 
    //點(diǎn)擊返回或前進(jìn)時(shí),需要將page放到localStorage
    window.localStorage.pageIndex = page;
  });

      將頁面中所有改變pageIndex的地方,同時(shí)放到localStorage。這樣刷新頁面的時(shí)候就可以取到當(dāng)前頁的pageIndex。

      上面的方法都是將pageIndex放到了state參數(shù)里,還有一種方法是把它放到第三個(gè)參數(shù)url里,也就是說通過改變當(dāng)前頁網(wǎng)址的辦法。pageIndex從網(wǎng)址里面?。?/p>

 //當(dāng)前第幾頁
   var pageIndex = window.location.search.replace("?page=", "") || ;
   function nextPage(){
     //將頁面的index加
     ++pageIndex;
     //重新發(fā)請(qǐng)求和頁面加載
     makeRequest(pageIndex);
     window.history.pushState(null, null, "?page=" + pageIndex);
   }

      注意,一旦執(zhí)行了第8行的pushState,當(dāng)前網(wǎng)址的地址就會(huì)發(fā)生變化。

      有一點(diǎn)需要注意的是,window.history.length雖然返回是的當(dāng)前隊(duì)列的元素個(gè)數(shù),但不代表history本身就是那個(gè)隊(duì)列,通過不同瀏覽器的對(duì)history[i]的輸出:

   可以看到history是一個(gè)數(shù)組,它的作用是讓用戶拿到history.length,當(dāng)前的長度,但是填充的內(nèi)容是不確定的。 

      除了使用history之外,還有借助hash的方法,網(wǎng)易新聞就是使用了這樣的方法:

   //當(dāng)前第幾頁
   var pageIndex = window.location.hash.replace("#page=", "") || ;
   function nextPage(){ 
     makeRequest(pageIndex);
     window.location.hash = "#page=" + pageIndex;
   }
   window.addEventListener("hashchange", function(){
     var page = window.location.hash.replace("#page=", "") || ;
     makeRequest(page);
   });

      關(guān)于支持性,參考caniuse網(wǎng)站:history IE10及以上支持,hashchange的支持性較好,IE8及以上都支持。

      雖然hashchange的支持性較好,但是history的優(yōu)點(diǎn)是可以傳數(shù)據(jù)。對(duì)一些復(fù)雜的應(yīng)用可能會(huì)有很大的發(fā)揮作用,同時(shí)history支持back/go操作。

以上本文關(guān)于h5的history改善ajax列表請(qǐng)求體驗(yàn),希望大家喜歡。

您可能感興趣的文章:
  • 使用ajax和history.pushState無刷新改變頁面URL示例
  • 基于h5 ajax實(shí)現(xiàn)手機(jī)定位(demo)
  • 基于Jquery.history解決ajax的前進(jìn)后退問題

標(biāo)簽:林芝 洛陽 鄭州 邢臺(tái) 舟山 海南 內(nèi)蒙古 遼源

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《基于h5的history改善ajax列表請(qǐng)求體驗(yàn)》,本文關(guān)鍵詞  基于,的,history,改善,ajax,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《基于h5的history改善ajax列表請(qǐng)求體驗(yàn)》相關(guān)的同類信息!
  • 本頁收集關(guān)于基于h5的history改善ajax列表請(qǐng)求體驗(yàn)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章