浏览器后退按钮可恢复空字段

时间:2008-11-04 09:40:29

标签: internet-explorer back-button

我有一个网页x.php(位于我网站的密码保护区域),其中有一个表单和一个按钮,使用POST方法发送表单数据并打开{{1 }}。这非常有效。

但是,如果用户决定在Internet Explorer 7中导航回来,则原始x.php#abc中的所有字段都将被清除,并且必须再次键入所有内容。我无法在会话中保存发布的信息,我试图了解如何让IE7按照我想要的方式运行。

我在网上搜索并找到了建议HTTP标头应包含显式缓存信息的答案。目前,我试过这个:

x.php

及其变体。没有成功。使用诸如WireShark之类的工具查看返回的标题,向我展示了Apache确实尊重我的标题。

所以我的问题是:我做错了什么?

6 个答案:

答案 0 :(得分:11)

IE 自动保留表单内容,只需按下后退按钮:

  • 您没有使用no-cache pragma或类似的
  • 破坏缓存
  • 相关的表单字段不是由脚本
  • 动态创建的

你似乎手头有缓存,所以我猜测后者可能适用。 (正如mkoeller所说,如果页面在最后几次后退点击中,通过保持页面本身的活动时间长于屏幕上的时间,Firefox可以避免此问题。但这是可选的,Firefox将恢复到与IE和其他相同的行为浏览器一旦你浏览了几页,它已经过期了。)

如果您是从脚本onload创建自己的表单字段,那么浏览器无法知道新输入控件与旧实例“相同”,因此它无法用以前的实例填充它 - 提交的值。在这种情况下,如果您希望它与后退按钮一起使用,您必须开始在客户端上存储数据。

然后你必须使用某种状态键,以便每组数据都与页面的一个实例相关联,否则会同时通过同一表单的多个实例或在表单上打开两个浏览器选项卡会严重混淆你的剧本。

然后然后如果它们是大型表单,你开始收集大量数据,如果你使用的客户端存储机制是cookie,你可能会开始丢失数据,如以及每个HTTP请求发送一堆不必要的状态无意义。其他客户端存储机制可用,但它们是特定于浏览器的。

简而言之:很好地完成动态生成的表单是一个巨大的痛苦,如果可以,最好避免。在页面上有一个隐藏的表单,脚本可以看到,从而允许浏览器执行他们的字段记忆 - 魔术而不是给你任务,通常要容易得多。

答案 1 :(得分:4)

在尝试进一步缩小问题的范围时,我找到了问题的原因。我正在使用由Apache重写的URL(即我总是将我的页面作为http://foo.com/page访问,由Apache映射到http://foo.com/page.htm)。只要我指定了正确的HTTP标头(Cache-ControlExpires等),使用真实网址解决了问题并使IE7满意。

以下是我在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"

答案 2 :(得分:3)

Firefox做这种缓存。据我了解你的问题,你希望IE7的行为与Firefox一样。我认为这是不可能的。

Firefox和IE7在解释后退按钮的方式上有所不同。

Firefox将显示上一页的DOM树,因为它是在页面离开之前最后显示的。也就是说,所有表单数据仍将包含在表单的输入字段中。但是,在按下后退按钮时,您将看不到onload事件。

IE7将根据从服务器收到的响应再次呈现页面。因此,表单是emtpy(除非服务器最初发送了默认值),但您会看到onload事件。

答案 3 :(得分:2)

我p了一下,这是一个非常难的问题。它也是动态修改内容的主要痛苦。你访问该页面,javascript用你的指令增加它,你转到下一页,然后回来,javascript已经忘记了。并且没有办法简单地更新页面服务器端,因为页面来自缓存。

所以我设计了一个后退按钮缓存。

它的邪恶和糟糕的网络,但它使页面能够表现人们期望他们的行为,而不是在整个地方神奇地扭曲。

<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>

这会有一点神奇之处在于它会检测您当前/正在查看的页面是否是从缓存加载的。

如果您第一次在那里,它会检测到“无哈希”,并将“#_”添加到页面网址。 如果您在第一次使用&gt;(即:不是指向该页面的直接链接),该页面上已经有#_,因此它将其删除,并在删除它的过程中,触发页面重新加载。

答案 4 :(得分:1)

您可以在字段中使用autocomplete =“off”。 这样,浏览器不会缓存这些值,因此当用户单击后退按钮时,不会在表单中填充值。

答案 5 :(得分:1)

这是旧帖子,此后发生了很大变化。尽管如此,我的一种表单还是遇到了这个问题(但是Chrome起作用了。)如果返回,它将清除所有信息。我发现这种变通办法是完全巧合的,因此需要在这里分享它,因为那太奇怪了。可能这不是发布此信息的最佳地点,但是我们开始吧。

这就是我所拥有的(精简版,无法正常工作)。

<table>
    <form>
    <tr>
        <td><input type="number" value="0"></td>
    </tr>
    </form>
</table>

这已解决(现在可以正常工作。)将<form>标签移到<table><tr>标签之外。

<form>
<table>
    <tr>
        <td><input type="number" value="0"></td>
    </tr>
</table>
</form>