この記事は主に、h5 履歴に基づいた ajax リストリクエストエクスペリエンスの改善に関する関連情報を紹介します。必要な友人はそれを参照してください。
「次のページ」をクリックすると、多くの Web サイトがページネーションで表示されます。ページの更新を避けるために動的リクエスト方式を採用しています。誰もが ajax を使用しますが、細かい点から長所と短所を区別することができます。細かい点は、ブラウザの「戻る」キーと「進む」キーをサポートする機能です。この記事では、ブラウザーで前後に移動できるようにする 2 つの方法、または新しいページにリダイレクトするのと同じように、Ajax に前のページに戻ったり次のページに進んだりできるようにする 2 つの方法について説明します。
ページングでデータを表示する最も簡単な方法は、URL の後に複数のページ番号を追加し、「次のページ」をクリックすると、Web ページが page+1 の新しいアドレスにリダイレクトされます。たとえば、新浪のニュース ネットワークは、URL を次のように変更することでこれを行っています:index_1、index_2、index_3...ただし、このリストがページの主要部分ではない場合、またはページの他の部分に多くの画像やその他の豊富な要素がある場合、たとえば、ナビゲーションは大きなスライダーであり、この方法を使用すると、ページ全体が激しくちらつき、多くのリソースを再ロードする必要があります。したがって、DOM を動的に変更するには、ajax リクエストを使用します。
ただし、通常の動的リクエストでは URL は変更されません。ユーザーが次のページをクリックしたり、いくつかのページをクリックして前のページに戻りたい場合は、ブラウザのリターン キーをクリックする可能性があります。 , 戻るときは最初に閲覧していたページではなく、前のURLに戻ります。例えばCCTVのニュースネットワークはこんな感じです。 ajax リクエストから始めて、完全なケースで分析してみましょう。
デモを作りました
まず、リクエストを書きます:
//当前第几页 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='nextPage();'>下一页</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 を追加します。このイベントは、ユーザーがこれら 2 つのボタンをクリックするとトリガーされます。ただし、このイベントを検出するだけでは十分ではありません。つまり、前のページに戻るときに、そのページの pageIndex を知る必要があります。この目的は、履歴の PushState メソッドによって実現できます。pushState(pageIndex) は、現在のページの pageIndex を保存し、このページに戻るときに pageIndex を取得します。 PushState のパラメータは次のとおりです:
window.history.pushState(state, title, url);
ここで、state は現在のページのデータを保存するために使用されるオブジェクトです。タイトル title は含まれません。この URL が変更されると、それに応じてブラウザのアドレス バーのアドレスも変更されます。
そこで、次のページ データをリクエストする nextPage 関数に、もう 1 つのステップを追加します:
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; });
状態データはイベントを通じて渡されるため、pageIndex を取得できます。 。
ただし、この実装にはまだ問題があり、2 番目のページでページを更新すると、以下に示すように混乱が発生します。まず、次のページをクリックして 2 番目のページに移動し、次にページを更新します。最初のページが表示され、次のページをクリックすると、2 番目のページが表示されます。クリックするまでは、最初のページが表示されません。もう一度戻る:
右から 初めて戻るをクリックしたときに取得した pageIndex が 1 のままであることがツールバーからわかります。この状況では、以下に示すように履歴モデルを分析する必要があります。
は、アクセスした各 URL と状態データを含むアクセス記録を保存するキューを持っています。最初、キューの最初のポインタはページ = 0 の位置を指します。次のページがクリックされると、pushState が実行され、要素がキューに挿入され、この要素の URL と状態データが記録されます。 PushState オペレーション。 ここで、pushState 操作の最も重要な機能は、ブラウザの戻るボタンがグレー表示にならないように履歴キューに要素を挿入し、その後に前述のデータを保存することであることがわかります。 「戻る」をクリックすると、ヘッド ポインタが 1 ステップ戻ってページ = 0 の位置を指し、「前へ」をクリックすると、ヘッド ポインタが前に移動してページ = 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列表请求体验,希望大家喜欢。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
以上がh5 履歴に基づいて Ajax リスト リクエストのエクスペリエンスを改善するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。