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

IT技术 javascript jquery hash scrollto
2021-01-29 08:37:46

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

当它完成动画时,我像这样设置哈希

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;

            }
    });
});
6个回答

有一种解决方法是在现代浏览器上使用历史 API 并回退旧浏览器:

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

幸得利·贝罗

@DavidCook - 我们也可以使用history.replaceState(对于散列更改,这可能更有意义)来避免需要popstate事件侦听器。
2021-03-24 08:37:46
这对我有用。我喜欢历史变化的效果。我想补充一点,这不会触发hashchange事件。这是我必须解决的问题。
2021-03-24 08:37:46
不需要使用history.pushState来解决此行为。如果您的:target元素position: fixed已从正常流中删除,则无处滚动。然后您可以使用分配哈希值window.history.hash = 'foo',窗口将保持不变。
2021-03-31 08:37:46
在我看来,这是更好的答案。
2021-04-08 08:37:46
请注意,pushState 具有向浏览器历史堆栈添加状态的侧面(缩进)效果。换句话说,当用户单击后退按钮时,除非您还添加一个 popstate 事件侦听器,否则什么都不会发生。
2021-04-10 08:37:46

问题是您将window.location.hash设置为元素的 ID 属性。浏览器跳转到该元素是预期的行为,无论您是否“preventDefault()”。

解决此问题的一种方法是使用任意值作为哈希前缀,如下所示:

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);
这是实际回答问题的唯一解决方案 - 允许散列而不跳转
2021-03-19 08:37:46
很好的解决方案,但削弱了 OPs 解决方案,因为它否定了书签部分的使用
2021-04-02 08:37:46
这确实回答了解释添加和删除散列的任意值以避免根据默认浏览器行为进行跳转的问题。
2021-04-03 08:37:46

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

要设置它:

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

阅读它:

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

由于它与页面中的锚点或 id 不匹配,因此不会跳转。

将哈希设置为:window.location.hash = '#/' + id;,然后将其替换为:window.location.hash.replace(/^#\//, '#');将稍微美化 url -> projects/#/tab1
2021-03-25 08:37:46
我必须保持与 IE 7 和网站的某些移动版本的兼容性。这个解决方案对我来说是最干净的。一般来说,我会关注 pushState 解决方案。
2021-04-08 08:37:46

为什么不获取当前滚动位置,将其放入变量中,然后分配散列并将页面滚动放回原来的位置:

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

这应该有效

嗯,这对我有用了一段时间,但在过去几个月的某个时候,它在 Firefox 上停止了工作......
2021-03-16 08:37:46

我对现代浏览器使用了 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引擎不是很快,您可以注意到滚动的增加和减少,产生了令人讨厌的视觉效果。