保留动态更改的HTML在返回按钮上

50

太神奇了,我经常在其他网站看到这个功能,但从没在我工作的网站上看到过。

我正在使用ajax引入新内容,我知道有history.js和History API,但我不想更改URL,只是希望浏览器缓存新HTML内容,以便当用户离开页面并通过后退按钮返回时,仍然具有更新后的HTML内容。

我经常在其他网站看到这个功能,而且它们没有更改URL或使用哈希#标记。
有什么技巧可以让它正常工作,还是由浏览器随机决定?
如果我不想使用URL来传递信息,有没有更简单的替代方案?


那么将页面的“状态”保存在cookie中怎么样?例如,客户端已单击以显示登录框,然后您将该操作保存在名为“login = 1”的cookie中,每当客户端返回时,您使用JavaScript读取cookie并显示登录。尽管我认为这不是“最佳”解决方案,因为可能有太多要“处理”的“选项”。 - HamZa
2
是的,cookie、session和localstorage都是保存状态的好方法,就像参数一样,可以重新加载。但我看到其他网站在没有使用这些方法的情况下也能正常工作。即使整个页面都是用ajax构建的,当我点击后退按钮时,它们也没有任何视觉延迟。他们是如何做到的呢? - Madd0g
也许他们在onload之前构建页面,而浏览器应该在缓存HTML时加载。 - A.M.K
一些浏览器具有“后退-前进缓存”、“快速历史导航”或“页面缓存”功能,这些功能根据某些条件应用于网站。请参见https://webkit.org/blog/427/webkit-page-cache-i-the-basics/。 - 4esn0k
5个回答

42

在过去的十年半中,我发现了两个技巧,曾通过痛苦的试验和错误找到: 输入字段值 - 特别是“hidden”值 - 与 URL 一起保存在浏览器的历史记录中 - 而且返回页面时会调用 onLoad 事件。

这意味着您可以在隐藏字段(请记得将它们放入表单中)中存储尽可能多的“状态”,然后在 “onLoad” 上重新执行更改。 我通常将“渲染”部分作为一个单独的函数...换句话说,在动态发生时,我首先写入隐藏字段,然后调用渲染函数。 然后,我将所有不同的渲染功能汇总在一起,针对各种动态性并从 onLoad 调用它们。

我要强调的是,我从未在任何手册中查找过这些信息 - 因此无法提供任何保证 - 但我已经可靠地使用它一段时间了(从 Netscape 开始!!!)。 它适用于“许多”浏览器(所有 IE、Chrome、Firefox-至于其他浏览器,我从未尝试过。)

如果有人知道更“正确”和不那么乏味的方法,我很乐意听到。 但是这似乎已经可以解决问题了。


3
嘿Groover,谢谢回复,我明白如何手动完成(即保存状态“参数”,然后在用户返回页面时重新加载)。问题是,我看到许多ajax网站(如其他评论中所述的使用firefox),当我按下返回键时HTML仍然存在,根本不需要重新加载。我很想了解这是如何实现的。 - Madd0g
2
重新阅读您的回复后,我想进一步指出,我描述的技术不需要实际的服务器访问来“重新加载”页面 - 或任何部分 - 或修改URL等 - 效果是当您按下返回按钮返回到页面时,所有动态更改都会在第一次查看页面时神奇地就位 - 无论是通过ajax放置在那里 - 还是仅仅通过求和列的数字。如果这已经被理解了,请原谅我。 :) - Groover
等等,我可能误解了你的回答,你有使用这种方法成功的URL吗?听起来很有趣,但在尝试自己实现之前,我想问一下是否有示例,如果你有的话。谢谢!|编辑:所有事情都必须在onload之前发生才能工作?那么对于分页(+在onload之后发生的事情),它不应该起作用? - Madd0g
没关系!我明白你的意思了,当然表单字段是被保存的!使用autocomplete=on甚至可以在刷新后保留,也许。哇,非常聪明,我该如何给你更多积分哈哈 - Madd0g
有点奇怪,昨晚在FF上还能百分之百地工作,现在输入字段却无法被记住。在Chrome上测试完美运行!尝试调整“Cache-Control”没有改变FF的情况...看来我只能使用Chrome了。 - Brad G
显示剩余4条评论

9

我是 RES 的作者,在 /r/javascript 找到了你的问题。

显然,Firefox 最近添加了自己完成此操作的功能,但当浏览器无法为您完成此操作时,没有“好”的方法可以完成此操作。

RES 以前所做的是添加一个 #page=n 标记,其中 n 是您的页码。这样,在页面加载时,如果已经有 location.hash,RES 就知道您必须是通过返回按钮进入的 -- 不幸的是,这种特定行为会破坏 Firefox 和 Chrome 中的 ctrl-f 查找功能,因为查找会导致您滚动到另一页(page = n+1),因为哈希更改会关闭查找对话框,这会让用户感到烦恼...

因此,现在 RES 做了一些丑陋和不完美的体操来猜测您是否通过返回按钮到达该页面。每次加载新页面时,它都会将该数字保存在 sessionStorage 中(类似于 localStorage,但仅限于选项卡),并在通过返回按钮显示时发送该页面号的请求。

但是:最近我在 FF 和 Chrome 中进行了测试,似乎哈希更改不再“取消” ctrl-f 查找对话框,因此我的建议是您使用它。在页面加载时,如果存在哈希,请加载由该哈希确定的相关数据。

如果您想要变得非常疯狂,还可以将实际的 HTML 内容存储在 localStorage 中,并在通过返回按钮重新加载页面时重新加载它。这可能不是最有效的方法,并且几乎肯定会导致依赖于 DOM 的 JavaScript 发生冲突,因此请谨慎行事!

“最佳”解决方案实际上取决于您的网站正在做什么/该内容的外观/行为如何。


感谢回复,很有趣了解历史。就像 RES 中的 NER 一样,我的网站只是在页面内加载新的内容页,而不是使用传统的分页。与 reddit 类似,这些页面本身并没有真正独立存在,因此更新 URL(从而允许用户复制永久链接)将会导致混淆,我想避免这种情况。但看起来这不可行。这也不是一个真正的要求,只是我希望能够避免的事情。谢谢! - Madd0g
我希望我能给出一个更好的答案,而不是“当浏览器无法为您完成时,没有”好“的方法来解决这个问题。”。我想我永远不会知道为什么它在Reddit上有效而在我的网站上无效。无论如何,还是谢谢。 - Madd0g
据我所知,只有FF才能在Reddit上保存NER的状态。你是说你也看到Chrome保存了吗? - honestbleeps
我不是常规用户,但我在Chrome上测试了几次,它不起作用。但在Firefox上却非常出色。我在其他网站上也看到过,他们像NER一样在ajax调用之后更改URL,如果您离开页面并返回,则修改后的HTML仍然存在,无需重新加载。 - Madd0g
是的,当他们在ajax调用之后更改URL时,那就是HTML5的pushState / popState功能。如果没有URL更改,你可能会有点倒霉,因为所有浏览器(除了最近版本的Firefox)大部分都会“在任何javascript加载之前将页面恢复到之前的状态”。 - honestbleeps

1
您可以使用History.js实现您的目标,像这样:
function manageHistory(data){

    var History = window.History;
    if ( !History.enabled ) { return false; }        
    History.replaceState({myData: data}, null);
}

$('select.select').change(function(e) { // I am using select tag here to give an example of an HTML action triggerer

    e.preventDefault(); 

    // get data from your select tag

    manageHistory( data)


});

History.Adapter.bind(window, 'statechange', function() { 
    var State = History.getState();

    // Launch the ajax call and update DOM using State.data.myData
});

根据Mozilla网站上关于History的文档,PushState方法的第三个参数是:

URL — ....... 此参数是可选的;如果没有指定,它将设置为文档的当前URL。


谢谢,我知道如何做了。我使用了history.js插件完成了它,但它只是在ajax调用时保存页面滚动位置。我尝试过pushState和replaceState。在这两种情况下,当我使用后退按钮时,我创建的HTML在页面加载后消失了。 - Madd0g

0

我认为原因可能是其他网页使用了一些提供会话的后端服务器。

如果您正在构建静态的HTML/JS页面,那么就没有这样的会话,页面只会重新加载。

您可以使用cookie来实现您想要的功能。


除非将页面的大量HTML存储在本地存储中,否则我看不到如何在没有任何重绘的情况下还原所有内容,这是瞬间完成的。仅将最后一页的参数保存在内存中并使用Ajax调用会产生一些可见的变化,并需要更长的时间。 - Madd0g

0

本地存储是一种方式,另一种方式是服务器端持久化。

当在客户端编辑/创建/更改某些属性时,您需要通过WebStorage或数据库通过RESTful API(或类似的东西)同步页面状态更改。

当您返回页面时,页面可以从本地存储中检索存储的信息...如果您正在使用服务器端持久性,则需要与会话cookie一起使用它以检索用户的状态更改-然后可以从服务器加载。


这在谷歌浏览器中似乎不起作用。即使缓存头被设置为不缓存,浏览器似乎也会缓存 ajax 获取消息。 - Roey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接