Home  >  Article  >  Web Front-end  >  Improve the ajax list request experience based on h5 history

Improve the ajax list request experience based on h5 history

亚连
亚连Original
2018-05-24 14:47:541537browse

This article mainly introduces the relevant information based on h5 history to improve the ajax list request experience. Friends who need it can refer to it

Websites with rich information are usually displayed in paging. Click "Next" page", many websites use dynamic requests to avoid page refreshes. Although everyone is ajax, you can still distinguish the pros and cons from some small details. A small detail is the ability to support the browser's "back" and "forward" keys. This article discusses two methods that allow the browser to go back and forward, or let ajax have the ability to return to the previous page or advance to the next page just like redirecting to a new page.

The simplest way to display data in paging is to add multiple page numbers after the URL, and when you click "Next Page", the web page will be redirected to the new address of page 1. For example, Sina's news network does this by changing the URL: index_1, index_2, index_3... But if this list is not the main part of the page, or there are many pictures and other rich elements in other parts of the page, for example, the navigation is a large slider, and if you use this method, the entire page will flicker violently, and many resources will have to be re- load. So use ajax request to dynamically change the DOM.

But ordinary dynamic requests will not change the URL. When the user clicks on the next page, or clicks on a few pages, and wants to return to the previous page, he may click the return button of the browser. key, this will cause the return not to the page originally viewed, but to the previous URL. For example, CCTV’s news network is like this. Let's start with the ajax request and analyze it with a complete case.

Made a demo

First, write a request:

 //当前第几页
  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); 
      }
    }
  }

Render after getting the data:

  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); 
  }

Such a basic ajax request is set up, and then responds to the "next page" button:

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

At this point, if no processing is done, the browser's return and forward buttons cannot be used. role.

If you can detect when the user clicks the back and forward buttons, you can write some articles. h5 adds such an event window.onpopstate. This event will be triggered when the user clicks those two buttons. But it is not enough to detect this event. You must also be able to pass some parameters. That is to say, when returning to the previous page, you must know the pageIndex of that page. This purpose can be achieved through the pushState method of history. pushState(pageIndex) stores the pageIndex of the current page, and then obtains the pageIndex when returning to this page. The parameters of pushState are as follows:

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

where state is an object{}, used to store the data of the current page, and the title is not very big The role of url is the url of the current page. Once this url is changed, the address in the browser address bar will also change accordingly.

Therefore, in the nextPage function that requests the next page data, add one more step:

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

Then listen to the popstate event:

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

The state data is passed in through the event. This way you can get the pageIndex.

However, there are still problems with this implementation. If you refresh the page on the second page, confusion will occur, as shown below: First, click the next page to go to the second page. page, and then refresh the page, the first page appears, then click the next page, and the second page appears. When I click Return, a problem occurs. The second page is still displayed, not the expected first page. It is the first page until I click Return again. Page:

From the toolbar on the right, you can find that the pageIndex obtained when you click Return for the first time is still 1. For this situation, the history model needs to be analyzed, as shown below:

# can be understood as the operation of history. The browser has a queue to store access records. Including each visited URL and state data. At the beginning, the first pointer of the queue points to the position of page = 0. When the next page is clicked, pushState is executed, an element is inserted into the queue, and the url and state data of this element are recorded through the pushState operation. It can be seen here that the most important function of the pushState operation is to insert elements into the history queue so that the browser's back button is not in a grayed out state, followed by the storage of data mentioned above. When you click back, the head pointer moves back one step to point to the position of page = 0, and when you click forward, it moves forward to point to the position of 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的作用分析

The above is the detailed content of Improve the ajax list request experience based on h5 history. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn