使用“后退”按钮时,Div 的类不会持续存在

Posted

技术标签:

【中文标题】使用“后退”按钮时,Div 的类不会持续存在【英文标题】:Div's Class not persisting when 'back' button is used 【发布时间】:2011-03-31 13:43:55 【问题描述】:

我有一个包含两个 div 的 ASP.NET 页面。两者都有搜索字段和包含在其中的搜索按钮。当我第一次来到这个页面时,Div A 的类是“SearchDiv”,而 Div B 的类是“SearchDivDisabled”。这些类改变了外观,因此用户知道他们当前启用了哪种搜索类型。

当点击 Div B 时,javascript 将其类更改为“SearchDiv”,并​​将 Div A 更改为“SearchDivDisabled”。这一切都像一个魅力。我遇到的问题是当用户更改为 Div B,单击 Div B 的搜索按钮(显然重定向到结果页面),然后使用浏览器的后退按钮。当他们返回搜索页面时,Div A 再次启用,而 Div B 被禁用,即使他们上次使用 Div B。在搜索按钮事件处理程序中,我在重定向之前设置了 Div 的类属性,希望这会更新服务器上的页面,因此当用户返回时,他们最后启用的 Div 仍将启用(无论第一次访问该页面时启用了哪个)。

我相信这涉及 ViewState,但我不确定为什么不保存类属性,所以当用户返回页面时它会被恢复。这里有什么我遗漏的东西,或者有什么简单的方法可以保证我想要的行为吗?谢谢!

编辑:这是按钮事件处理程序代码:

protected void RedirectToResults(int searchEnum, string resultPage)

    ShowContainer(searchEnum);
    Response.Redirect(resultPage + this.webParams.getAllVariablesString(null));


  protected void ShowContainer(int searchContainerToShow)
  
     if (searchContainerToShow < 0 || searchContainerToShow > SearchContainers.Count || SearchContainers.Count == 0)
        return;

     //disable all search panels
     foreach (SearchContainer container in SearchContainers.Values)
     
        container.searchDiv.Attributes.Add("class", "SearchDivDisabled");
     

     //enable selected panel
     SearchContainers[searchContainerToShow].searchDiv.Attributes.Add("class", "SearchDiv");
  

RedirectToResults() 是从实际的按钮事件处理程序中调用的,枚举代表选定的搜索面板和结果页面 url。 SearchContainers 是一个将整数映射到搜索 Div 的字典。重要的代码是最后一行,我在其中使用“活动”搜索类更新选定的搜索容器,而不是禁用的(我分配给其他 div(s))

其他更新:过去几天我一直在与这个问题作斗争。我有点能够让以下代码工作(在 page_load 中):

        Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
        Response.AppendHeader("Expires", "0"); // Proxies.

但这确实不是一个解决方案,因为正确缓存的其他所有内容都丢失了,这让我比开始时更糟糕。其他一切似乎都很好,只是 div 的类导致我挣扎。

编辑:只是想为遇到此问题的其他人更新此内容。虽然我相信这里有一个解决方案,可以设置页面的可缓存性以强制浏览器回发,但我无法让它在所有浏览器上 100% 工作(主要是 Firefox 让我适应,这是一个记录在案的错误)。我确实相信 cookie 解决方案会起作用,但我觉得这可能比仅仅尝试存储几个 div 的状态所必需的要复杂一些。

我最终做的是将 div 的类与其相关单选按钮的状态联系起来(div 旁边有单选按钮,允许用户以更直观的方式启用搜索面板)。我注意到这些单选按钮在使用后退按钮时保留了正确的选中值,因此我可以保证它们会指示要启用的正确 div。因此,在 JavaScript 的 onload 中,我检查启用了哪个单选按钮,然后相应地调整搜索 div 的类。这是一个相当大的 hack,但在所有浏览器上都 100% 有效,并且只用了大约 10 行 JavaScript。

【问题讨论】:

【参考方案1】:

我认为 ViewState 不是这里的问题;它可能需要在客户端 javascript 代码中进行管理,因为客户端上的切换状态不会自动反映在服务器上...

您可能想查看的是通过历史记录点功能管理浏览器历史记录:http://msdn.microsoft.com/en-us/library/cc488548.aspx

HTH。

【讨论】:

【参考方案2】:

因为您回帖不是为了更改 div 的样式,所以当用户点击后退按钮时,它会将其恢复为页面最初发布的方式。解决这个问题的简单方法是让按钮触发一个切换样式的回发。

【讨论】:

正如我上面提到的,'在搜索按钮事件处理程序中,我在重定向之前设置了 Divs 的类属性,希望这会更新服务器上的页面,因此当用户返回时,他们的最后-启用的 Div 仍将启用'所以我正在这样做。我将使用代码更新原始帖子。【参考方案3】:

在搜索按钮中执行重定向之前,您可以将当前设置为“SearchDiv”类的 div 的 id 存储在 SESSION 变量中,在搜索页面的加载期间获取 div 并在其上设置适当的类。 这样你就可以继续使用你的 javascript 来切换 div 上的类,并且只在重定向到不同的页面之前保存数据,避免不必要的发布

【讨论】:

这个问题是 OnLoad() 在使用后退按钮时不会触发。因此,无论会话中存储了什么,当用户返回搜索页面时,我都无法更改任何内容,因为它都是客户端。 Kevin,搜索页面中的 OnLoad() 没有被触发,因为页面是从缓存中获取的。添加 Response.Cache.SetCacheability(HttpCacheability.NoCache);在您的搜索页面的 Page_Load 函数中,查看单击后退时是否触发了事件【参考方案4】:

正如我在之前的回答中提到的,您可以使用会话变量来实现您所需要的一切。 既然您提到了持久的 DIV 选择,我就要求您将其包含在会话变量中。 如果您希望其他表单数据也被持久化以及将它们全部转储到会话变量中(确保在完成它们时清理它们)

这将是您满足要求的最简单方法。

你也在使用

Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
    Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
    Response.AppendHeader("Expires", "0"); // Proxies.

你可以简单使用

Response.Cache.SetCacheability(HttpCacheability.Private);

在您的 Page_load 中并实现相同的功能

如果您有任何具体的问题,请告诉我。

【讨论】:

只是想对此添加评论。 Firefox 是一个问题,因为它基本上无视页面上的“可缓存性”标志,并且会缓存它想要的任何内容。在 IE 中,这往往会起作用,但如果你想获得跨浏览器的支持,我还没有找到一种在使用“返回”导航到页面时强制 FF 回发的好方法。【参考方案5】:

将设置存储在客户端的 cookie 中,然后在页面加载时通过 JavaScript 检查 cookie 并更改 CSS 类。解决此问题的其他方法可能不起作用,因为当用户点击 Back 按钮时,并不总是从服务器请求该页面。

使用 jQuery cookie plugin

// this function will update the style of the divs based on the cookie's settings
function updateClass()
    var val = $.cookie('myCookieName');

    // set your div's class
    if (!val || val=='divA')
    
        $('#divA').removeClass('SearchDivDisabled');
        $('#divA').addClass('SearchDiv');
        $('#divB').removeClass('SearchDiv');
        $('#divB').addClass('SearchDivDisabled');
    else
        $('#divB').removeClass('SearchDivDisabled');
        $('#divB').addClass('SearchDiv');
        $('#divA').removeClass('SearchDiv');
        $('#divA').addClass('SearchDivDisabled');
    


// call this passing in 'divA' or 'divB' depending on which is selected
function updatePage(selectedDiv)
    $.cookie('myCookieName', selectedDiv,  path: '/', expires: 10 );
    updateClass();


// change the class of the divs when the page is finished rendering
$(document).ready(function()updateClass();):

【讨论】:

【参考方案6】:

这可以通过一种两种方式解决。

如果每个搜索表单发布到不同的 URL,则每个 URL 都应设置一个会话变量,例如,称为“LastSearchMethd”,为“A”或“B”。 如果他们都发布到同一个 URL,那么只需为每个表单分别包含一个包含“A”或“B”的隐藏字段,并将提交的值保存在会话变量中。

无论哪种方式,您都需要根据会话变量的值来渲染每个 DIV 的样式。

正如其他发帖者所提到的,正确的缓存也是一个考虑因素。

【讨论】:

【参考方案7】:

当您使用 Chrome 中的“后退”按钮返回页面时,对 DOM 的大多数更改都不会保留。 (我相信这在其他浏览器中可能会有所不同,因为它们实现了 BFcache(后向缓存),目前正在为 Chrome 开发。)

然而,保留的是输入值,例如单选按钮和隐藏输入。 因此,如果您将更改存储在(隐藏的)输入中,您可以在pageshow event 上恢复您的 DOM。 (如果您查看 Mozilla 页面,对活动的支持似乎马马虎虎,但 CanIUse.com 更乐观:https://www.caniuse.com/#search=pageshow)

【讨论】:

以上是关于使用“后退”按钮时,Div 的类不会持续存在的主要内容,如果未能解决你的问题,请参考以下文章

如何使表单数据在“从缓存重新加载”时持续存在

当资源不是本地的(使用 http)时,不会触发 Cordova android 4.x 后退按钮事件

Jquery Mobile 嵌套列表 - 后退按钮不见了?

使用浏览器后退按钮时如何强制重新加载页面?

后退按钮的背景图像在触摸 iOS 7 之前不会出现

当后退按钮按下销毁应用程序时,Flutter Android Platform EventChannel 不会停止