7

フォームと、フォームデータを送信して開くメソッドを使用するボタンがあるWebページx.php(私のWebサイトのパスワードで保護された領域)があります。これはかなりうまくいきます。POSTx.php#abc

ただし、ユーザーがInternet Explorer 7に戻ることにした場合は、元のフィールドのすべてのフィールドx.phpがクリアされ、すべてを再入力する必要があります。投稿された情報をセッションに保存できず、IE7を希望どおりに動作させる方法を理解しようとしています。

Webを検索したところ、HTTPヘッダーに明示的なキャッシュ情報が含まれている必要があることを示唆する回答が見つかりました。現在、私はこれを試しました:

session_name("FOO");
session_start();
header("Pragma: public");
header("Expires: Fri, 7 Nov 2008 23:00:00 GMT");
header("Cache-Control: public, max-age=3600, must-revalidate");
header("Last-Modified: Thu, 30 Oct 2008 17:00:00 GMT");

およびそのバリエーション。成功せずに。WireSharkなどのツールで返されたヘッダーを見ると、Apacheが実際に私のヘッダーを尊重していることがわかります。

だから私の質問は:私は何が間違っているのですか?

4

6 に答える 6

14

IE、次の場合に限り、[戻る] ボタンのクリック時にフォームの内容を自動的に保持します。

  • no-cache プラグマなどでキャッシュを壊していない
  • 問題のフォーム フィールドがスクリプトによって動的に作成されていない

あなたはキャッシュを手にしているようですので、後者が当てはまると思います。(mkoeller が言うように、Firefox は、ページが最後の数回クリックされた場合、画面上よりも長くページ自体を存続させることにより、この問題を回避します。ただし、これはオプションであり、Firefox は IE や他のものと同じ動作に戻ります。数ページ先を閲覧し、古いページの有効期限が切れたら、ブラウザーを変更します。)

スクリプトのオンロードから独自のフォーム フィールドを作成している場合、ブラウザは新しい入力コントロールが古いインスタンスと「同じ」であることを認識できないため、以前に送信された値を入力できません。 . この場合、戻るボタンでうまく再生したい場合は、クライアントにデータの保存を開始する必要があります。

次に、ある種の状態キーイングを使用して、各データ セットがページの 1 つのインスタンスに関連付けられるようにする必要があります。そうしないと、同じフォームの複数のインスタンスを通過したり、フォームで 2 つのブラウザー タブを同時に開いたりすると、非常に混乱します。あなたのスクリプト。

そしてフォームが大きい場合は大量のデータを収集し始めます。使用しているクライアント側のストレージ メカニズムが Cookie である場合は、データを失い始める可能性があり、不要な無意味な状態の負荷を送信することもできます。すべての HTTP リクエスト。他のクライアント側ストレージ メカニズムも利用できますが、それらはブラウザー固有です。

要するに、動的に生成されたフォームを適切に処理することは非常に苦痛であり、可能であれば回避するのがおそらく最善です。スクリプトが可視化するページに非表示のフォームを配置することで、ブラウザーがユーザーにタスクを与えるのではなく、フィールドを記憶する魔法を実行できるようにする方が、通常ははるかに簡単です。

于 2008-11-04T11:16:26.677 に答える
4

問題をさらに絞り込もうとしているうちに、問題の原因が見つかりました。http://foo.com/page私は Apache によって書き換えられた URL を使用していました (つまり、Apacheによって にマップされているページに常にアクセスしていましたhttp://foo.com/page.htm)。適切な HTTP ヘッダー ( 、など)を指定する限り、実際のURLを使用することで問題が解決し、IE7 が快適になりました。Cache-ControlExpires

すべてのブラウザーがキャッシュに満足しているように見えるヘッダーを出力するために PHP コードで行うことは次のとおりです。

function emitConditionalGet($timestamp)
{
    // See also http://www.mnot.net/cache_docs/
    // and code sample http://simonwillison.net/2003/Apr/23/conditionalGet/

    $gmdate_exp    = gmdate('D, d M Y H:i:s', time() + 1) . ' GMT';
    $last_modified = gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
    $etag          = '"'.md5($last_modified).'"';

    // If the client provided any of the if-modified-since or if-none-match
    // infos, take them into account:

    $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
                       ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false;
    $if_none_match     = isset($_SERVER['HTTP_IF_NONE_MATCH'])
                       ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])     : false;

    if (!$if_modified_since && !$if_none_match)
    {
        return;  // the client does not cache anything
    }

    if ($if_none_match && $if_none_match != $etag)
    {
        return;  // ETag mismatch: the page changed!
    }
    if ($if_modified_since && $if_modified_since != $last_modified)
    {
        return;  // if-modified-since mismatch: the page changed!
    }

    // Nothing changed since last time client visited this page.

    header("HTTP/1.0 304 Not Modified");
    header("Last-Modified: $last_modified");
    header("ETag: $etag");
    header("Cache-Control: private, max-age=1, must-revalidate");
    header("Expires: $gmdate_exp");
    header("Pragma: private, cache");
    header("Content-Type: text/html; charset=utf-8");
    exit;
}

function emitDefaultHeaders($timestamp)
{
    $gmdate_exp    = gmdate('D, d M Y H:i:s', time() + 1) . ' GMT';
    $last_modified = gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
    $etag          = '"'.md5($last_modified).'"';

    header("Last-Modified: $last_modified");
    header("ETag: $etag");
    header("Cache-Control: private, max-age=1, must-revalidate");
    header("Expires: $gmdate_exp");
    header("Pragma: private, cache");
    header("Content-Type: text/html; charset=utf-8");
}

function getTimestamp()
{
    // Find out when this page's contents last changed; in a static system,
    // this would be the file time of the backing HTML/PHP page. Add your
    // own logic here:
    return filemtime($SCRIPT_FILENAME);
}

// ...

$timestamp = getTimestamp();
emitConditionalGet($timestamp);
emitDefaultHeaders($timestamp); //previously, this variable was mistyped as "$timestaml"
于 2008-11-04T14:30:56.550 に答える
3

Firefox はこの種のキャッシュを行います。私があなたの質問を理解しているように、あなたは IE7 が Firefox のように動作することを望んでいます。それは不可能だと思います。

Firefox と IE7 では、戻るボタンの解釈方法が異なります。

Firefox は、ページが離れる前に最後に表示されたように、前のページの DOM ツリーを表示します。つまり、すべてのフォーム データがフォームの入力フィールドに含まれたままになります。onloadただし、戻るボタンを押してもイベントは表示されません。

IE7 は、サーバーから受信した応答に基づいてページを再度レンダリングします。したがって、フォームは空ですが (サーバーから送信されたデフォルト値が最初にあった場合を除きます)、onloadイベントが表示されます。

于 2008-11-04T10:06:28.737 に答える
2

私は突っついたが、これはかなり難しい問題だ。また、動的に変更されたコンテンツのお尻の大きな痛みです。あなたはそのページにアクセスし、javascriptはあなたの指示でそれを補強し、あなたは次のページに行き、そして戻ってきます、そしてjavascriptは忘れてしまいました。また、ページはキャッシュから出てくるため、サーバー側でページを単純に更新する方法はありません。

そこで、back-button-cache-breakerを考案しました。

その邪悪でウェブに悪いですが、それはページがいたるところに魔法のように歪むのではなく、人々が彼らが期待するように振る舞うことを可能にします。

<script type="text/javascript">//<!-- <![CDATA[
(function(){
    if( document.location.hash === "" )
    {
        document.location.hash="_";
    }
    else
    {
      var l = document.location;
      var myurl = ( l.protocol + "//" + l.hostname + l.pathname + l.search); 
      document.location = myurl;
    }
})();
//]]> --></script>

これは、/現在/表示しているページがキャッシュからロードされたかどうかを検出するという点で少し魔法をかけます。

初めてアクセスする場合は、「ハッシュなし」が検出#_され、ページのURLに「」が追加されます。初めてアクセスする場合(つまり、ページへの直接リンクではない場合)、ページにはすでに#_が付いているため、ページが削除され、削除の過程でページの再読み込みがトリガーされます。

于 2008-11-04T10:45:18.673 に答える
2

フィールドで autocomplete="off" を使用できます。この方法では、ブラウザによって値がキャッシュされないため、ユーザーが [戻る] ボタンをクリックしたときに値がフォームに入力されません。

于 2008-11-04T12:12:08.373 に答える