你能否在不影响历史记录的情况下使用哈希导航?

108

很抱歉,这可能是不可能的,但是否有一种方法可以更改URL的哈希值而不在浏览器历史记录中留下条目并且不需要重新加载?或者进行等效操作?

具体来说,我正在开发基本的哈希导航,如下所示:

//hash nav -- works with js-tabs
var getHash = window.location.hash;
var hashPref = "tab-";
function useHash(newHash) {
    //set js-tab according to hash
    newHash = newHash.replace('#'+hashPref, '');
    $("#tabs li a[href='"+ newHash +"']").click();
}
function setHash(newHash) {
    //set hash according to js-tab
    window.location.hash = hashPref + newHash;

    //THIS IS WHERE I would like to REPLACE the location.hash
    //without a history entry

}
    // ... a lot of irrelavent tabs js and then....

    //make tabs work
    $("#tabs.js-tabs a").live("click", function() {
        var showMe = $(this).attr("href");
        $(showMe).show();
        setHash(showMe);
        return false;
    });
    //hash nav on ready .. if hash exists, execute
    if ( getHash ){
        useHash(getHash);
    }

显然要使用jQuery。想法是在此特定情况下,1)使用户返回到每个选项卡更改可能会通过堆积不必要的引用有效地“破坏后退按钮”,2)如果用户刷新,则不保留他们当前所在的选项卡是一种恼人的问题。


如果您不想保留历史记录,为什么要更改哈希值? :| - Ionuț Staicu
11
刷新页面时最好呈现用户所在的标签页,但由于他们可能会在不同的标签页之间来回切换,将无谓地使历史记录中充满条目,导致后退按钮实际上变得不太有用。这只是一个例子,它可以适用于任何需要保存临时状态但又不想依赖cookie或填充用户临时文件的时间。当您刷新时,js内容仍然保持原样 - 您没有离开页面,并且它不是跳转点或伪页面,因此历史记录条目只会干扰标准导航。 - user241244
4个回答

113

location.replace("#hash_value_here"); 对我来说一直运行良好,直到我发现它在IOS Chrome上不起作用。此时,请使用:

history.replaceState(undefined, undefined, "#hash_value")

history.replaceState() 的操作方式与 history.pushState() 完全相同,只是 replaceState() 修改当前的历史记录条目而不是创建一个新的。

请记得保留 #,否则 URL 的最后一部分将被更改。


3
现代浏览器的完美选择;但要注意一些浏览器仅支持部分特性的会话历史管理。 - Matt
2
@BramVanroy 不需要,使用后者就足够了。 - Lucia
2
除非您使用:target选择器,否则历史记录功能将无用,因为规范的这部分(CSS与历史操作的交互)目前似乎未定义,并且大多数/所有浏览器在历史替换时不会重新计算样式。 - morphles
2
仅供参考:history.replaceState()location.replace()在Chrome历史记录中仍会创建条目,这在某些情况下可能被视为不可接受:https://dev59.com/cl8d5IYBdhLWcg3weiB- - Grief
4
注意:有趣的是,history.replaceState(...)不会触发window.onhashchange事件,而location.replace会。很奇怪,对吧? - Matt
显示剩余6条评论

105
location.replace("#hash_value_here"); 

上述代码似乎实现了您所期望的功能。


4
就是这样。如果你有 URI 段,使用 location.replace(window.location + "#hash") 将会保留它们。 - tedders
7
赞成这种方法,更加简洁清晰,希望它被标记为正确答案。 - joeellis
15
window.location.replace(('' + window.location).split('#')[0] + '#' + hash); 简化为只更新哈希部分。 - johnstorm
1
我正在Windows 8下的Chrome 30中进行测试,如果我进入Chrome历史记录并在我的测试URL下选择“从此网站获取更多信息”,那么我可以看到所有使用此方法添加的哈希值。 - TechAurelian
2
请注意,location.replace('#hash_value_here')仅更改哈希片段而不是路径,因此不会触发页面加载...除非文档包含基本标记:<base href ="http://example.com/" />如果确实包含基本标记,则当您仅使用前导“#hash_value_here”调用replace方法时,实际上就好像您说了location.replace('http://example.com/#hash_value_here')。 当您在具有路径片段的页面上并且没有意识到已设置基本标记时,这似乎很明显,但却是一个陷阱。 - Tyler Kasten
显示剩余7条评论

6

编辑:现在已经过去了几年,浏览器也有所发展。

@Luxiyalu的答案是正确的方法。

--旧回答--

我也认为这是不可能的(目前)。但如果您不打算使用哈希值,为什么需要更改它呢?

我相信我们作为程序员使用哈希值的主要原因是让用户收藏我们的页面或在浏览器历史记录中保存状态。如果您不想执行任何操作,则只需将状态保存在变量中并从那里工作即可。

我认为使用哈希的原因是要使用我们无法控制的值。如果您不需要它,则可能意味着您可以控制所有内容,因此只需将状态存储在变量中并处理它即可。(我喜欢重复自己)

我希望这可以帮助您。也许您的问题有更简单的解决方案。

更新:

  1. 设置第一个哈希,并确保它在浏览器历史记录中保存。
  2. 当选择新选项卡时,执行window.history.back(1),这将使历史记录从您的第一个初始化哈希开始后退。
  3. 现在设置新哈希,因此选项卡切换将仅在历史记录中产生一个条目。

您可能需要使用一些标志来知道当前条目是否可以通过返回“删除”,或者是否跳过第一步。 并确保在强制执行history.back时不执行“哈希”的加载方法。


很有可能我错过了一些基础知识(疲劳是个好借口,我就用这个吧),但你是在说我可以设置一个变量,在重新加载后保留其更改后的值吗?除了使用 cookie 之外?(某种程度上,cookie 看起来有点过度了..)也许这就是不清楚的地方。我将在重新加载时使用哈希值 - 特别是哈希值。感谢您的回复! - user241244
好的,所以在重新加载后,您将使用一些信息值。很不幸,哈希值会被某些浏览器历史记录选中。很抱歉,但根据我的经验,cookie 是您最好的选择。如果您想要一些浏览器历史记录无法检测到但在重新加载后仍然保留的东西,那么只能使用 cookie。如果用户点击了一个链接,那么您可以设置链接为查询(?mystate=greatness),即使它不需要是 ajax,您也可以保存信息以供 JavaScript 在初始化请求时读取。 - guzart
我曾经想过可以使用哈希值,然后检查历史记录,如果已添加则将其删除。但是经过一些研究,似乎JS访问“history”受到安全限制。因此,无法删除保存在历史记录中的信息。 - guzart
啊,好的。太兴奋了,开始测试错误的东西。这不会起作用,因为刷新不会保留选项卡状态,这就否定了使用哈希的意义。非常好的想法,但很遗憾,似乎不可能实现。 - user241244
可能是浏览器特定的问题。我在Firefox 3.6,Chrome 3.0.195,IE 8.0.76,Safari 4.0.4,Opera 10.10中尝试过,它们都会在我刷新后保留哈希值。 - guzart
显示剩余3条评论

-2

您可以始终创建一个事件监听器,以捕捉超链接上的单击事件,并在回调函数中放置e.preventDefault(),这应该可以防止浏览器将其插入历史记录。


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