如何在不跳转文档的情况下更新 window.location.hash?

我在我的网站上设置了一个滑动面板。

当它完成动画制作后,我像这样设置散列

function() {
window.location.hash = id;
}

(这是一个回调,id在前面分配)。

这个工作得很好,允许用户将面板标记为书签,也允许非 JavaScript 版本工作。

但是,当我更新散列时,浏览器会跳转到该位置。我想这是预期的行为。

我的问题是: 我怎样才能防止这种情况发生?也就是说,如果存在散列,那么如何更改窗口的散列,但是 没有让浏览器滚动到元素?event.preventDefault()之类的?

我使用的是 jQuery 1.4和 ScrollTo 插件

非常感谢!

更新

下面是更改面板的代码。

$('#something a').click(function(event) {
event.preventDefault();
var link = $(this);
var id = link[0].hash;


$('#slider').scrollTo(id, 800, {
onAfter: function() {


link.parents('li').siblings().removeClass('active');
link.parent().addClass('active');
window.location.hash = id;


}
});
});
185550 次浏览

问题是您正在将 Window.location.hash设置为元素的 ID 属性。浏览器跳转到该元素是预期的行为,而不管您是否“预防默认()”。

解决这个问题的一个方法是在 hash 前面加上一个任意值,如下所示:

window.location.hash = 'panel-' + id.replace('#', '');

然后,所有您需要做的就是检查页面加载上的前缀散列。作为额外的奖励,你甚至可以平滑滚动到它,因为你现在在控制散列值..。

$(function(){
var h = window.location.hash.replace('panel-', '');
if (h) {
$('#slider').scrollTo(h, 800);
}
});

如果您需要这个工作在任何时候(而不仅仅是在初始页面加载) ,您可以使用一个函数来监视散列值的更改,并动态跳转到正确的元素:

var foundHash;
setInterval(function() {
var h = window.location.hash.replace('panel-', '');
if (h && h !== foundHash) {
$('#slider').scrollTo(h, 800);
foundHash = h;
}
}, 100);

为什么你不得到当前的滚动位置,把它放在一个变量中,然后分配散列,并把页面滚动回到原来的位置:

var yScroll=document.body.scrollTop;
window.location.hash = id;
document.body.scrollTop=yScroll;

这应该能行

在现代浏览器上使用历史 API 有一个解决方案,可以回到旧的浏览器上:

if(history.pushState) {
history.pushState(null, null, '#myhash');
}
else {
location.hash = '#myhash';
}

这要归功于 Lea Verou

廉价而肮脏的解决方案. . 使用丑陋的 # ! 风格。

设定:

window.location.hash = '#!' + id;

阅读:

id = window.location.hash.replace(/^#!/, '');

因为它不匹配并且不在页面中锚定或 id,所以它不会跳转。

我不确定是否可以修改原始元素,但是将 id attr 转换为诸如 data-id 之类的东西怎么样?然后只需读取 hash 值的 data-id 值,它就不会跳转。

我将 Attila Fulop (Lea Verou)解决方案与 Gavin Brock 解决方案结合起来用于现代浏览器,具体如下:

if (history.pushState) {
// IE10, Firefox, Chrome, etc.
window.history.pushState(null, null, '#' + id);
} else {
// IE9, IE8, etc
window.location.hash = '#!' + id;
}

正如 Gavin Brock 所观察到的,要捕获回 id,您必须处理字符串(在本例中可以有或没有“ !”)如下:

id = window.location.hash.replace(/^#!?/, '');

在此之前,我尝试了一个类似 user706270提出的解决方案,但它并不能很好地处理 Internet Explorer,因为它的 Javascript 引擎不是很快,你可以注意到滚动条的增加和减少,这产生了一个讨厌的视觉效果。

这个办法对我很有效。

设置 location.hash的问题在于,如果在页面上找到该 id,页面将跳转到该 id。

window.history.pushState的问题在于,它为用户单击的每个选项卡向历史记录中添加了一个条目。然后,当用户单击 back按钮时,他们转到前一个选项卡。(这可能是你想要的,也可能不是。这不是我想要的)。

对我来说,replaceState是更好的选择,因为它只替换当前历史记录,所以当用户单击 back按钮时,他们转到前一页。

$('#tab-selector').tabs({
activate: function(e, ui) {
window.history.replaceState(null, null, ui.newPanel.selector);
}
});

看看 MDN 上的 历史 API 文档

在使用 laravel 框架时,我在使用 path-> back ()函数时遇到了一些问题,因为它擦除了我的散列。为了保持散列,我创建了一个简单的函数:

$(function() {
if (localStorage.getItem("hash")    ){
location.hash = localStorage.getItem("hash");
}
});

我把它设置在我的另一个 JS 函数中,像这样:

localStorage.setItem("hash", myvalue);

您可以任意命名您的本地存储值; 我的值命名为 hash

因此,如果在 PAGE1上设置了哈希,然后导航到 PAGE2; 当您单击 PAGE2上的 Back 时,哈希将在 PAGE1上重新创建。

这个办法对我很有效

// store the currently selected tab in the hash value
if(history.pushState) {
window.history.pushState(null, null, '#' + id);
}
else {
window.location.hash = id;
}


// on load of the page: switch to the currently selected tab
var hash = window.location.hash;
$('#myTab a[href="' + hash + '"]').tab('show');

我的全部 js 代码是

$('#myTab a').click(function(e) {
e.preventDefault();
$(this).tab('show');
});


// store the currently selected tab in the hash value
$("ul.nav-tabs > li > a").on("shown.bs.tab", function(e) {
var id = $(e.target).attr("href").substr(1);
if(history.pushState) {
window.history.pushState(null, null, '#' + id);
}
else {
window.location.hash = id;
}
// window.location.hash = '#!' + id;
});


// on load of the page: switch to the currently selected tab
var hash = window.location.hash;
// console.log(hash);
$('#myTab a[href="' + hash + '"]').tab('show');