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

时间:2010-10-06 06:46:49

标签: javascript jquery hash scrollto

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

完成动画制作后,我就像这样设置哈希

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

(这是一个回调,之前已分配id。)

这很好用,允许用户为面板添加书签,也可以让非JavaScript版本工作。

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

我的问题是:如何防止这种情况发生?即如何更改窗口的哈希值,但如果哈希存在,浏览器会滚动到该元素?某种event.preventDefault()类的东西?

我正在使用jQuery 1.4和scrollTo plugin

非常感谢!

更新

以下是更改面板的代码。

$('#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;

            }
    });
});

9 个答案:

答案 0 :(得分:225)

有一种解决方法是在现代浏览器上使用历史记录API,并对旧版本进行回退:

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

信用转到Lea Verou

答案 1 :(得分:49)

问题是您将 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);

答案 2 :(得分:26)

便宜又讨厌的解决方案..使用丑陋的#!风格。

设置它:

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

阅读:

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

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

答案 3 :(得分:13)

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

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

这应该有效

答案 4 :(得分:10)

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

答案 5 :(得分:1)

我不确定你是否可以改变原始元素但是如何从使用id attr切换到像data-id这样的东西呢?然后只需读取哈希值的data-id值,它就不会跳转。

答案 6 :(得分:0)

这个解决方案对我有用。

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

window.history.pushState的问题在于它为用户点击的每个标签添加了一个条目。然后,当用户单击back按钮时,它们将转到上一个选项卡。 (这可能是也可能不是你想要的。这不是我想要的。)

对我而言,replaceState是更好的选择,因为它只会替换当前的历史记录,因此当用户点击back按钮时,它们会转到上一页。

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

查看MDN上的History API docs

答案 7 :(得分:0)

在使用laravel框架时,由于使用了route-> back()函数,这会抹掉我的哈希,因此出现了一些问题。为了保持哈希值,我创建了一个简单的函数:

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

并将其设置在我的其他JS函数中,如下所示:

localStorage.setItem("hash", myvalue);

您可以根据自己的喜好命名本地存储值;我的名为hash

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

答案 8 :(得分:0)

此解决方案对我有用

// 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');