2

私は最も効果的な方法でブラウザの履歴を操作するためのクリーンな解決策を見つけようとしています。(私はGWTを使用していますが、この質問は実際にはそれよりも一般的です。)

これが私の状況です(私はそれがかなり標準的だと思います):

私はいくつかの異なるページ/場所/場所(あなたがそれを呼びたいものは何でも)を持っているウェブアプリケーションを持っています、そしてそれは私がブラウザの履歴の変更に応じて表示します。ほとんど静的なHTMLページである通常の「ホーム」、「機能」、「連絡先」などの他に、ユーザーが自分のユーザーアカウントにログインして(それを「プロジェクト」と呼びましょう)「ユーザー」セクションがあります。セクション。ユーザーはプロジェクトに取り組むことができます。

そのため、今では、#Home 、#Features、 Contactなどのローカルリンクと、 #User # Projectを使用してさまざまなページにアクセスしています。そして、次のシナリオを除いて、すべてが正常です。

たとえば、誰かがリンク#Projectを開くと、その人にはプロジェクトのログインダイアログが表示されます。このログインダイアログにはcancelボタンがあります。これは、アプリからブラウザーのボタンを呼び出すだけで実装backできます(簡単です)。私がこれをしたい理由は2つあります:

  1. このログインダイアログには、アプリ内のいくつかの異なる場所やブックマークからアクセスできます。このアプローチでは、ユーザーがどこから来たのかを追跡する必要はありません。
  2. さらに重要なのは、ユーザーがどこから来たのか(たとえば、#Home)を覚えていて、ユーザーを「転送」してその場所に戻るようにリンクした場合、次のような効果が得られることです。
    • ユーザーが#Home、次に#Featuresにアクセスし、プロジェクトのログインをクリックするとします。
    • ユーザーがボタンをクリックし、私がユーザーを#Featurescancelに「転送」した場合、後でブラウザーのボタンをクリックすると、ログインダイアログが戻り、次に#Features、最後に#Homeが表示されます。本当にあなたが期待するものではありません。back
    • 代わりに、すぐに#Homeに戻りたいと思いますcancel。これは、ブラウザーのback関数を介して実装した場合に得られるものです。

この時点では、ユーザーが最初に#Projectへの直接ブックマークリンクを介してこのログインダイアログに移動する場合を除いて、すべてが素晴らしいです。なぜなら、私が単にcancel=を持っている場合back、ユーザーはページから完全にブラウザのスタートページまたは以前の場所に戻されるからです。したがって、この場合、「転送」を#Homeにリンクする必要があります。

今、私はこれを修正するためのいくつかの方法を考えて、いくつかの解決策を考え出しましたが、どれも私にとって非常に望ましいとは思えませんが、とにかくそれらを共有して、創造性を刺激するかもしれません:

  • ページを最初に開いたときに、履歴トークンを取得します。キャンセル可能なダイアログをトリガーするのが#Projectまたは#Userまたはその他の場合は、次のアイテムを履歴スタックに配置します:#Home#Project、最後のアイテムは保存された初期トークンです。これにより、私のcancelボタンが正しく機能するようになります...一度...しかし、ユーザーがback後でクリックすると、ログインダイアログが再び表示されます(元の履歴トークンはまだ履歴スタックにあり、私にはわかりません)それをクリアする方法)。次にクリックするcancelと、彼はページから外れます(一貫性のない動作)。
  • 代わりに、 #+++、 # Home、 # Projectをスタックに配置することもできます。これにより、 #+++リンクを検出し、#を再度追加するだけでbackユーザーをページから外すクリックをキャッチできます。スタックへのホームトークン。これは問題を解決し、全体的に美しく機能しますが、戻るボタンをすばやく押すことなくWebサイトから戻ることができないWebサイトは嫌いです...
  • 最もクリーンな解決策は、アプリ内の場所に関する限り、履歴スタックの長さを何らかの方法で追跡できればです。最初は簡単です。1つのアイテムがあります。しかし、次のような一連の場所を取得した場合はどうなりますか:#Home#Features#Home?ユーザーはクリックして#Homebackに戻りましたか、つまり、履歴はブラウザで長さ1になりましたか、それとも#Homeリンクをクリックしましたか、つまり履歴は長さ3ですか?これを検出するための私の考えは次のとおりです。
    • #Homeは#homeと同じであることを定義します
    • ページ内のすべてのリンクは、大文字のリンクのみにリンクしてください。
    • 大文字で始まる履歴変更通知を受け取ったら、すぐに2つの項目を履歴に追加します。最初の項目は小文字で始まり、2番目の項目も大文字で始まります。つまり、 #Homeは#Home、# homeHomeに変わります。
    • 小文字で始まる履歴の変更を取得した場合は、ユーザーbackがリンクではなくクリックしただけで、backさらに2回クリックするだけで、実際に前のページに戻ることができます。
    • これで、「後方」リンクと「前方」リンクを区別し、コード内で正確な履歴モデルを維持できます。
    • しかし、残念ながら、これには2つの問題があります。1つは、ブラウザの履歴ががらくたで雑然としていること(あまりエレガントではない)、2つ目は、ユーザーがbackアプリをクリックしないほど速くクリックすると、システムが故障し始めることです。メッセージに反応する時間があります。

これは非常に一般的な問題のようです。皆さんの1人が、これまでの私の考えよりも有用な方向性を示してくれることを願っています。

4

3 に答える 3

1

window.historylength現在のタブの履歴にエントリがいくつあるかを示す属性があります。残念ながら、フィルタリングすることはできません(したがって、言う方法はありませんwindow.history.localURLs.length)。

これをほぼ完全にクライアント側で行っている場合 (つまり、部分的な更新、ページ全体の読み込みがほとんどなく、ハッシュまたはhistory.(push|pop)StateAPI を使用している場合) は、クライアント側のルーティング フレームワークをアプリケーションに組み込んで、再ルーティングを回避することを検討してください。車輪を発明。

于 2012-11-27T03:33:09.357 に答える
1

ユーザーが #LOGIN ダイアログにアクセスする前に、エントリ ポイント クラスが実行されます。このクラスでは、最後に認識されたページを思い出すことができます。ログイン アクティビティ/プレゼンターでは、最後に認識された場所が null かどうかを確認するブラウザー履歴イベント ハンドラーを追加できます。null の場合、ユーザーを #HOME ページに送信します。

ユーザーがアプリ内のどの場所にアクセスしたかをブラウザに尋ねる必要はありません。必要に応じて、各セッションの全履歴を思い出すことができます: [#HOME, #LOGIN, #FEATURES, #HOME].

于 2012-11-28T02:53:57.513 に答える
0

あなたはどうですかQueue<String> historyQueue;

ページが初めてロードされるとき、onModuleLoad()つまりQueue. 履歴イベントをキャプチャするときは、それが元の履歴トークンか新しい履歴トークンかを確認してください。バックの場合はキューからポップアウトし、新しい場合はキューに追加します。このように、キャンセル ボタンはtoken = historyQueue.pop()トークンが null かどうかをチェックするだけです。もしそうなら、あなたが言っback = cancelたように、適切なことをしてください。

于 2012-11-28T00:13:25.540 に答える