首頁 web前端 js教程 基於h5的history改善ajax清單請求體驗

基於h5的history改善ajax清單請求體驗

May 24, 2018 pm 02:47 PM
ajax history html5

這篇文章主要介紹了基於h5的history改善ajax列表請求體驗的相關資料,需要的朋友可以參考下

信息比較豐富的網站通常會以分頁顯示,在點“下一頁」時,很多網站都採用了動態請求的方式,避免頁面刷新。雖然大家都是ajax,但從一些小的細節還是 可以分辨優劣。一個小的細節是能否支援瀏覽器「後退」和「前進「鍵。本文討論兩種方法,讓瀏覽器可以後退和前進,或者說讓ajax就像重定向到新頁面一樣 擁有能夠返回到上一頁或前進到下一頁。

      資料實現分頁顯示,最簡單的做法是在網址後面加上多個page的當數,點「下一頁」時,讓網頁重新導向到page 1的新位址。例如新浪的新聞網就 是這麼做的,透過改變網址實現:index_1、index_2、index_3…。但是如果這個清單並不是頁面的主體部分,或者頁面的其它部分有很多圖片等豐富元素,例如導航是一個很大的slider,再使用這樣的方式,整個頁面會閃爍得厲害,並且很多資源得重新載入.所以使用ajax請求,動態改變 DOM。

      但是普通的動態的請求不會使網址發生變化,用戶點了下一頁,或者點了第幾頁,想要返回到上一個頁面時,可能會去點瀏覽器的返回鍵,這樣就導致返回的時候不是返回到原先查看的頁面了,而是上一個網址了。例如央視的新聞網就是這樣的。以下從ajax請求開始說起,以一個完整的案例進行分析。

      做了一個demo

   首先,寫一個請求:

 //当前第几页
  var pageIndex = 0;
  //请求函数
  function makeRequest(pageIndex){
    var request = new XMLHttpRequest();
    request.onreadystatechange = stateChange;
    //请求传两个参数,一个是当前第几页,另一个是每页的数据条数
    request.open("GET", "/getBook?page=" + pageIndex + "&limit=4", true);
    request.send(null);
    function stateChange(){
      //状态码为4,表示loaded,请求完成
      if(request.readyState !== 4 ){
        return;
      }
      //请求成功
      if(request.status >= 200 && request.status < 300 || request.status === 304){
        var books = JSON.parse(request.responseText);
        renderPage(books); 
      }
    }
  }
登入後複製

     拿到資料後進行渲染:

  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=&#39;nextPage();&#39;>下一页</button>";
    var section = document.createElement("section");
    section.innerHtml = bookHtml;
    document.getElementById("book").appendChild(section); 
  }
登入後複製

這樣一個基本的ajax請求就搭起來了,然後再響應「下一頁」按鈕:

  function nextPage(){
    //将页面的index加1
    pageIndex++;
    //重新发请求和页面加载
    makeRequest(pageIndex);
  }
登入後複製

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

      若能夠偵測使用者點擊了後退、前進按鈕的話,就可以做些文章。 h5就是增加了這麼一個事件window.onpopstate,當使用者點擊那兩個按鈕就會觸 發這個事件。但是光偵測到這個事件是不夠的,還得能夠傳些參數,也就是說回到之前那個頁面的時候得知道那個頁面的pageIndex。透過 history的pushState方法可以達到這個目的,pushState(pageIndex)將目前頁的pageIndex存起來,再回到這個 頁面時取得到這個pageIndex。 pushState的參數如下:

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

      其中state為object{},用來存放目前頁面的數據,title標題沒有太大的作用,url為目前頁面的url,一旦更改了這個url,瀏覽器網址列的位址也會跟著改變。

      於是,要求下一頁資料的nextPage函數裡面,加上多一步操作:

  function nextPage(){
    pageIndex++;
    makeRequest(pageIndex);
    //存放当前页面的数据
    window.history.pushState({page: pageIndex}, null, window.location.href); 
  }
登入後複製

然後監聽popstate事件:

  //如果用户点击返回或者前进按钮
  window.addEventListener("popstate", function(event){
    var page = 0;
    //由于第一页没有pushState,所以返回到第一页的时候是没有数据的,因此得做下判断
    if(event.state !== null){
      page = event.state.page;
    }
    makeRequest(page); 
    pageIndex = page;
  });
登入後複製

     state資料透過event傳進來,這樣就可以得到pageIndex。

但是,這樣實作還有問題,在第二頁的時候如果刷新頁面的話,會發生錯亂,如下所示:首先點下一頁到第二頁,然後刷新頁面,出現第一頁,再點下一頁,出現第二頁,點返回時出現問題,顯示還是第二頁,不是期望的第一頁,直到再次點返回時才是第一頁:

 從右邊的工具列可以發現,點第一次回傳的時候取得的pageIndex仍然是1。對於這種情況,需要分析history模型,如下所示:

 可以理解為對history的操作,瀏覽器有一個佇列,用來存放存取的記錄,包括每個存取的網址還有state資料。一開始,佇列的首指標指向page = 0的位置,點下一頁時,執行了pushState,在這個佇列插入了一個元素,同時透過pushState操作記錄了這個元素的url和state資料。這裡可以看出,pushState的操作最重要的作用還是給history佇列插入元素,這樣瀏覽器的後退按鈕才不是置灰的狀態,其次才是上面說的存放 資料。點後退的時候,隊首指標後退一步指向page = 0的位置,點前進時又前進指向page = 1的位置。

如果在page = 1的位置刷新页面,模型是这个样子的:

在第2步刷新的时候,页面的pageIndex又恢复成默认值0,所以page = 0,显示第一页数据,但是history所用的队列并没有改变。然后再点下一页时,又给这个队列push了一个元素,这个队列就有两个pageIndex 为1的元素,所以必须得两次返回才能回到page = 0的位置,也就是上面说的错乱的情况。

根据上面的分析,这样的实现是有问题的,一但用户不是在page = 0的位置刷新页面,就会出现需要点多次返回按钮才能够回到原先的页面。

所以得在刷新的时候,把当前页的state数据更新一下,用replaceState,替换队列队首指针的数据,也就是当前页的数据。方法是页面初始化时replace一下:

window.history.replaceState({page: pageIndex /*此处为0*/}, null, window.location.href);
这样模型就变成:

但其实用户刷新的时候更希望的是还是显示当前页,而不是回到第一页。一个解决办法是用当前页的window.history.state数据,这个属性浏览器支持得比较晚。在页面初始化时设置pageIndex时就从history.state取:

var pageIndex = window.history.state === null ? 0 : window.history.state.page;
登入後複製

safari里面的history.state是最近执行pushState传入的数据,因此这个办法在chrome/firefox里面行得通,但是safari行不通。

第二种办法是借助h5的localStorage存放当前页数:

 //页面初始化,取当前第几页先从localStorage取
  var pageIndex = window.localStorage.pageIndex || 0;

  function nextPage(){
    //将页面的index加1,同时存放在localStorage
    window.localStorage.pageIndex = ++pageIndex;
    //重新发请求和页面加载
    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); 
    //点击返回或前进时,需要将page放到localStorage
    window.localStorage.pageIndex = page;
  });
登入後複製

将页面中所有改变pageIndex的地方,同时放到localStorage。这样刷新页面的时候就可以取到当前页的pageIndex。

上面的方法都是将pageIndex放到了state参数里,还有一种方法是把它放到第三个参数url里,也就是说通过改变当前页网址的办法。pageIndex从网址里面取:

 //当前第几页
   var pageIndex = window.location.search.replace("?page=", "") || ;
   function nextPage(){
     //将页面的index加
     ++pageIndex;
     //重新发请求和页面加载
     makeRequest(pageIndex);
     window.history.pushState(null, null, "?page=" + pageIndex);
   }
登入後複製

注意,一旦执行了第8行的pushState,当前网址的地址就会发生变化。

有一点需要注意的是,window.history.length虽然返回是的当前队列的元素个数,但不代表history本身就是那个队列,通过不同浏览器的对history[i]的输出:

可以看到history是一个数组,它的作用是让用户拿到history.length,当前的长度,但是填充的内容是不确定的。

除了使用history之外,还有借助hash的方法,网易新闻就是使用了这样的方法:

   //当前第几页
   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);
   });
登入後複製

      关于支持性,参考caniuse网站:history IE10及以上支持,hashchange的支持性较好,IE8及以上都支持。

      虽然hashchange的支持性较好,但是history的优点是可以传数据。对一些复杂的应用可能会有很大的发挥作用,同时history支持back/go操作。

以上本文关于h5的history改善ajax列表请求体验,希望大家喜欢。

上面是我整理给大家的,希望今后会对大家有帮助。

相关文章:

AJAX XMLHttpRequest对象详解

编写轻量ajax组件第三篇实现

Ajax请求中async:false/true的作用分析

以上是基於h5的history改善ajax清單請求體驗的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1318
25
PHP教程
1269
29
C# 教程
1248
24
HTML 中的表格邊框 HTML 中的表格邊框 Sep 04, 2024 pm 04:49 PM

HTML 表格邊框指南。在這裡,我們以 HTML 中的表格邊框為例,討論定義表格邊框的多種方法。

HTML 中的巢狀表 HTML 中的巢狀表 Sep 04, 2024 pm 04:49 PM

這是 HTML 中巢狀表的指南。這裡我們討論如何在表中建立表格以及對應的範例。

HTML 左邊距 HTML 左邊距 Sep 04, 2024 pm 04:48 PM

HTML 左邊距指南。在這裡,我們討論 HTML margin-left 的簡要概述及其範例及其程式碼實作。

HTML 表格佈局 HTML 表格佈局 Sep 04, 2024 pm 04:54 PM

HTML 表格佈局指南。在這裡,我們詳細討論 HTML 表格佈局的值以及範例和輸出。

HTML 輸入佔位符 HTML 輸入佔位符 Sep 04, 2024 pm 04:54 PM

HTML 輸入佔位符指南。在這裡,我們討論 HTML 輸入佔位符的範例以及程式碼和輸出。

HTML 有序列表 HTML 有序列表 Sep 04, 2024 pm 04:43 PM

HTML 有序列表指南。在這裡我們也分別討論了 HTML 有序列表和類型的介紹以及它們的範例

HTML onclick 按鈕 HTML onclick 按鈕 Sep 04, 2024 pm 04:49 PM

HTML onclick 按鈕指南。這裡我們分別討論它們的介紹、工作原理、範例以及各個事件中的onclick事件。

在 HTML 中移動文字 在 HTML 中移動文字 Sep 04, 2024 pm 04:45 PM

HTML 中的文字移動指南。在這裡我們討論一下marquee標籤如何使用語法和實作範例。

See all articles