完全なページと不完全なページ
アンカーナビゲーションについての
会話を続けます。 私たちの目標は、Grailsで実用的なアプリケーションを作成することです。
微妙な点が1つあります。 完全版(ヘッダー、ナビゲーションなどを含む)と省略形(AJAX呼び出し用)の両方でページを表示したいのです。 ただし、
/ my-app / do / receiptsと入力すると、
フルバージョンが取得されます。 これは次のようになります。
おっと! ページがメインである状況と内部である状況を何らかの方法で区別する必要があります。 これを行うには、小さなフィルターを作成します。
grails-app/conf/PartialPageLoadFilters.groovy
def filters = { partial(controller: "*", action: "*") { before = { // AJAX-? if (request.xhr) { // . request.partialPage = true } true } } }
Grailsを提供するマジック属性
request.xhrの使用に注意してください。 その存在は、現在の要求がAJAXを介して呼び出されることを意味します。 ほとんどのブラウザは、これを特別なHTTPヘッダーを介してサーバーに報告します。 上記では、すべてのAJAXリクエストを「内部」として宣言しましたが、実際のアプリケーションでは、状況はより複雑になる可能性があります。
これで、どこでも
request.partialPageフラグを使用できます。 内部ページ用に別のレイアウトを作成することもできますが、メインレイアウトにこのような挿入を愚かに行うことをお勧めします。
grails-app/views/layouts/main.gsp
%{-- --}% <g:if test="${request.partialPage}"> <g:layoutBody /> </g:if> <g:else> %{-- --}% <html> <head> ... </head> <body> ... <div id="pageContent"> <g:layoutBody /> </div> ... </body> </html> </g:else>
どのページオプションを表示するか(コントローラーおよびGSP)の完全な透明性を実現しました。
ブックマークと履歴
したがって、AJAXを介して切り替え可能な3つの画面があります。
/ my-app /#do /領収書 | / my-app /#do / buy | / my-app /#do /フィードバック |
---|
 |  |  |
すべてが非常にクールですが、結局のところ、「動的な」リンクをブックマークすることはできません。 実際には、サーバーに
送信され
ないアンカーテールが含まれています。 したがって、そのようなURLをロードするとき、サーバーはどの内部ページを表示するかを知りません。
アンカーのみがアンカーについて知っています。 これはソリューションを請います:最初にJavaScriptでベースページをロードし、次に現在のアンカーを定義するコードを実行し、AJAXを使用して内部をロードします。 特に気にすることなく、私はこのコードを書きました:
web-app/js/application.js
$.ready(function() { $('#pageContent').html('...') .load(buildURL(document.location.hash), function() {
このコードはアイデアのみを示しています。 必要に応じて、このコードをより美しい状態に仕上げることができますが、本質は変わりません。最初に基本ラッパーをダウンロードする必要があり、次にユーザーは内部パーツがロードされるのを待つ必要があります。 たとえば、Facebookは通常、内部が読み込まれるまで何も表示しません-好みの問題です。
しかし、話はどうですか? 戻る/進む遷移では、
$ .readyイベントは発生しません。 ブラウザは、このような遷移を、あるアンカーから別のアンカーへの「ホップ」、つまり ページをスクロールするだけです。 一意に識別可能なJavaScriptイベントは発生しません。 どうする
これを解決する1つの方法(それ自体は非常に残忍です)は、
document.location.hashプロパティの変更を定期的にチェックすることです。 突然現在のアンカーが変更された場合は、ページの内部をリロードする必要があります。
function checkLocalState() { if (document.location.hash && document.location.hash != currentState) { currentState = document.location.hash; $('#pageContent').html(' , ...') .load(buildURL(currentState), function() {
次に、500ミリ秒ごとにアンカーの変更を確認します。
$.ready(function() { setInterval(checkLocalState, 500); });
これで、アプリケーションはBack / Forward遷移に応答しますが、0.5秒の遅延が発生します。 この遅延(ユーザーに迷惑になることもあります)は、同様のナビゲーションスキームを使用している多くの大規模サイトで見られます。 間隔を短くすると、バックグラウンドJavaScriptはより多くのリソースを消費します。 間隔を長くすると、反応時間が長くなります。 一般的に、すべての費用を支払う必要があります。
まとめ
AJAXナビゲーションを備えたGrails + jQueryアプリケーションを作成しました。
- ページ全体をリロードせずに、ページの内部コンテンツのみをリロードします。
- ページの状態をアドレスバーに正しく保存します。 ブックマークや友人とのリンクの共有に適しています。
- ブラウザーの戻る/進む遷移に正しく応答します。
- ゲームの新しいルールに煩わされることなく、「古い方法で」サーバーコードを開発できます。 すべてのページ読み込みロジックが透過的になります(コントローラーおよびGSPページ用)。
- リンクは新しいウィンドウで開くことができ、正しく機能します。
- アプリケーションのリンクは、URLの先頭のポンド記号( # )を除いて、通常のリンクと同じです。 結局、jQuery-codeのリンクのすべてのロジックを慎重に実行しました。
もちろん、実際のアプリケーションでは、ここで指定するコードを改善する必要があります。特に、アンカーがない状況をより正確に考慮したり、より複雑なリンク構築スキームを使用したりする必要があります。 しかし、彼がアイデアをうまく実証し、アンカーナビゲーションの問題のほとんどを解決することを願っています。
参照:
- http://yensdesign.com/2008/11/creating-ajax-websites-based-on-anchor-navigation/
- GWTチュートリアル-履歴とハイパーリンクの管理