181

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

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

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;

            }
    });
});
4

9 回答 9

291

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

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

归功于 Lea Verou

于 2013-02-04T15:44:07.830 回答
54

问题是您将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);
于 2011-03-24T04:56:59.500 回答
30

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

设置它:

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

要阅读它:

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

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

于 2013-06-14T12:34:09.300 回答
13

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

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

这应该工作

于 2011-04-13T15:02:39.617 回答
11

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

于 2015-10-14T15:50:12.783 回答
4

这个解决方案对我有用。

设置的问题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 上的History API 文档

于 2018-04-28T14:04:25.767 回答
3

这个解决方案对我有用

// 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');
于 2018-11-14T10:24:07.623 回答
1

我不确定您是否可以更改原始元素,但是如何从使用 id attr 切换到其他类似 data-id 的元素?然后只需为您的哈希值读取 data-id 的值,它就不会跳转。

于 2013-10-31T23:16:25.457 回答
0

在使用 laravel 框架时,我在使用 route->back() 函数时遇到了一些问题,因为它删除了我的哈希值。为了保留我的哈希值,我创建了一个简单的函数:

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

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

localStorage.setItem("hash", myvalue);

你可以用任何你喜欢的方式命名你的本地存储值;我的名字叫hash.

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

于 2018-08-29T00:54:58.193 回答