Home>

More informative websites are usually displayed in paginated pages.When you click on "Next Page", many websites use dynamic requests.Avoid page refreshes.Although everyone is ajax, the advantages and disadvantages can be distinguished from some small details.A small detail is whether to support the browser "back" and "forward" keys. This article discusses two methods,Let the browser back and forward,Or to make ajax like redirecting to a new page, having the ability to return to the previous page or advance to the next page.

Data is displayed in pages,The easiest way is to add multiple page equivalents after the URL and click "Next Page" to redirect the page to the new address of page + 1.For example, Sina News Network does this.By changing the URL:index_1, index_2, index_3 ... But if the list is not the main part of the page,Or other parts of the page have a lot of rich elements like pictures,For example, navigation is a big slider, and then use this method,The entire page will flash violently,And many resources have to be reloaded.So use ajax request to change dom dynamically.

But ordinary dynamic requests will not change the URL,The user clicked on the next page,Or click on the first few pages,When i want to return to the previous page,May go to the browser's back button,As a result, when you return, you are not returning to the page you originally viewed.It was the previous URL.For example, CCTV News Network is like this.Let's start with the ajax request.Take a complete case study.

Made a demo

First, write a request:

//Current page
  var pageindex=0;
  //request function
  function makerequest (pageindex) {
    var request=new xmlhttprequest ();
    request.onreadystatechange=statechange;
    //Request two parameters,One is the current page number,The other is the number of data per page
    request.open ("get", "/getbook?page =" + pageindex + "&limit=4", true);
    request.send (null);
    function statechange () {
      //The status code is 4, meaning loaded, and the request is completed
      if (request.readystate! == 4) {
        return;
      }
      //The request was successful
      if (request.status>= 200&&request.status<300 || request.status === 304) {
        var books=json.parse (request.responsetext);
        renderpage (books);
      }
    }
  }

Get the data and render it:

 function renderpage (books) {
    var bookhtml =
      "<table>" +
      "<tr>" +
      "<th>book title</th>" +
      "<th>author</th>" +
      "<th>version</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;previous page</button>" +
      "<button onclick =" nextpage ();">Next page</button>";
    var section=document.createelement ("section");
    section.innerhtml=bookhtml;
    document.getelementbyid ("book"). appendchild (section);
  }

Such a basic ajax request is set up,Then respond to the "Next Page" button:

 function nextpage () {
    //Increment the page index by 1
    pageindex ++;
    //Resend the request and page load
    makerequest (pageindex);
  }
</pre>
</div>
<p>
At this point, if nothing is done,You cannot use the browser back and forward buttons.
</p>
<p>
If it is possible to detect that the user has clicked the back and forward buttons,You can do some articles.
h5 adds such an event window.onpopstate, which will be triggered when the user clicks those two buttons.
But detecting this event is not enough,You have to be able to pass some parameters,In other words, when returning to the previous page, you need to know the pageindex of that page. This can be achieved by the pushstate method of history,pushstate (pageindex) stores the pageindex of the current page, and then gets this pageindex when returning to this page. The parameters of pushstate are as follows:
</p>
<pre>
<code>
window.history.pushstate (state, title, url);

Where state is an object {}, which is used to store the data of the current page,The title title doesn't help much.The url is the url of the current page. Once this url is changed, the address of the browser address bar will also change.

So, in the nextpage function that requests the next page of data,One more step:

 function nextpage () {    pageindex ++;    makerequest (pageindex);    //Store the data of the current page    window.history.pushstate ({page:pageindex}, null, window.location.href);  }

Then listen to the popstate event:

 //If the user clicks the back or forward button  window.addeventlistener ("popstate", function (event) {    var page=0;    //Because there is no pushstate on the first page, there is no data when returning to the first page.So make a judgment    if (event.state! == null) {      page=event.state.page;    }    makerequest (page);    pageindex=page;  });

State data is passed in through events, so you can get pageindex.

However, there are still problems with this implementation,If you refresh the page on the second page,Chaos will happen,As follows:First click the next page to the second page,Then refresh the page,The first page appears,Click on the next page,The second page appears,There was a problem when the point returned,The display is still on the second page.Not the expected first page,It was not the first page until I clicked back again:

Can be found from the toolbar on the right,The pageindex obtained when the point was first returned is still 1. In this case,The history model needs to be analyzed as follows:

Can be understood as the operation of history, the browser has a queue,Used to store records of visits,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,Executed pushstate, inserted an element into this queue,At the same time, the url and state data of this element are recorded through the pushstate operation. As you can see here,The most important role of the pushstate operation is to insert elements into the history queue.Then the browser's back button is not grayed out.The second is the data stored above. When you step back,The head of the team stepped back to point to the position of page=0. When the point advances, it advances to the position of page=1.

If you refresh the page at page=1,The model looks like this:

When refreshing in step 2,The page index of the page is restored to the default value of 0, so page=0, displaying the first page of data,But the queue used by history has not changed.When you click on the next page,Pushed another element to this queue,This queue has two elements with a pageindex of 1, so it must return twice to return to the position of page=0, which is the messy situation mentioned above.

According to the analysis above,This implementation is problematic,Once the user does not refresh the page at page=0,It will appear that you need to click the back button multiple times to return to the original page.

So when refreshing,Update the state data of the current page,Replace the data of the first pointer of the queue with replacestate,That is the data of the current page.The method is to replace it when the page is initialized:

window.history.replacestate ({page:pageindex/* here 0 * /}, null, window.location.href);

So the model becomes:

But in fact, when the user refreshes, it is more desirable to display the current page.Instead of going back to the first page.One solution is to use the window.history.state data of the current page. This property browser supports late.When pageindex is set during page initialization, it is taken from history.state:

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

The history.state in safari is the data recently passed by the pushstate.So this method works in chrome/firefox,But safari doesn't work.

The second method is to use h5's localstorage to store the current number of pages:

//Page initialization,Take the current page first from localstorage
  var pageindex=window.localstorage.pageindex || 0;
  function nextpage () {
    //Increment the page index by 1 and store it in localstorage
    window.localstorage.pageindex=++ pageindex;
    //Resend the request and page load
    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);
    //When clicked to go back or forward,Need to put page to localstorage
    window.localstorage.pageindex=page;
  });

Place all changes in the page index on the page, and place them in localstorage. In this way, the page index of the current page can be obtained when the page is refreshed.

The above methods all put the pageindex in the state parameter, and another way is to put it in the third parameter url, that is, by changing the current page URL.pageindex is taken from the URL:

//Current page
   var pageindex=window.location.search.replace ("?page =", "") ||;
   function nextpage () {
     //Add the index of the page
     ++ pageindex;
     //Resend the request and page load
     makerequest (pageindex);
     window.history.pushstate (null, null, "?page =" + pageindex);
   }

Note that once the pushstate of line 8 is executed, the address of the current URL will change.

One thing to note is thatwindow.history.length returns the number of elements in the current queue,But does not mean that history itself is that queue,History [i] output from different browsers:

You can see that history is an array,Its role is to let users get history.length, the current length,But what is filled is uncertain.

In addition to using history, there are also methods that use hash. NetEase News uses this method:

  //Current page
   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);
   });

Regarding supportability,Reference caniuse website:history ie10 and above support,Hashchange has better support,ie8 and above are supported.

Although hashchange is more supportive,But the advantage of history is that you can transfer data.May be very useful for some complex applications,History supports back/go operations.

The history of h5 in this article improves the ajax list request experience.Hope you like it.

  • Previous ASPNET verification code implementation (with source code)
  • Next Learn with me var pre-parse and function declaration promotion