Javascript 如何在不跳转文档的情况下更新 window.location.hash?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3870057/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I update window.location.hash without jumping the document?
提问by alex
I have a sliding panel set up on my website.
我在我的网站上设置了一个滑动面板。
When it finished animating, I set the hash like so
当它完成动画时,我像这样设置哈希
function() {
window.location.hash = id;
}
(this is a callback, and the id
is assigned earlier).
(这是一个回调,并且id
早先分配了)。
This works good, to allow the user to bookmark the panel, and also for the non JavaScript version to work.
这很好用,允许用户为面板添加书签,并且非 JavaScript 版本也能正常工作。
However, when I update the hash, the browser jumps to the location. I guess this is expected behaviour.
但是,当我更新哈希时,浏览器会跳转到该位置。我想这是预期的行为。
My question is: how can I prevent this? I.e. how can I change the window's hash, but nothave the browser scroll to the element if the hash exists? Some sort of event.preventDefault()
sort of thing?
我的问题是:我怎样才能防止这种情况?即如何更改窗口的散列,但如果散列存在,则不让浏览器滚动到元素?某种event.preventDefault()
东西?
I'm using jQuery 1.4 and the scrollTo plugin.
我正在使用 jQuery 1.4 和scrollTo 插件。
Many thanks!
非常感谢!
Update
更新
Here is the code that changes the panel.
这是更改面板的代码。
$('#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;
}
});
});
回答by Attila Fulop
回答by Derek Hunziker
The problem is you are setting the window.location.hashto an element's ID attribute. It is the expected behavior for the browser to jump to that element, regardless of whether you "preventDefault()" or not.
问题是您将window.location.hash设置为元素的 ID 属性。浏览器跳转到该元素是预期的行为,无论您是否“preventDefault()”。
One way to get around this is to prefix the hash with an arbitrary value like so:
解决此问题的一种方法是使用任意值作为哈希前缀,如下所示:
window.location.hash = 'panel-' + id.replace('#', '');
Then, all you need to do is to check for the prefixed hash on page load. As an added bonus, you can even smooth scroll to it since you are now in control of the hash value...
然后,您需要做的就是在页面加载时检查前缀哈希。作为额外的好处,您甚至可以平滑滚动到它,因为您现在可以控制哈希值...
$(function(){
var h = window.location.hash.replace('panel-', '');
if (h) {
$('#slider').scrollTo(h, 800);
}
});
If you need this to work at all times (and not just on the initial page load), you can use a function to monitor changes to the hash value and jump to the correct element on-the-fly:
如果您需要它始终工作(而不仅仅是在初始页面加载时),您可以使用一个函数来监视哈希值的更改并即时跳转到正确的元素:
var foundHash;
setInterval(function() {
var h = window.location.hash.replace('panel-', '');
if (h && h !== foundHash) {
$('#slider').scrollTo(h, 800);
foundHash = h;
}
}, 100);
回答by Gavin Brock
Cheap and nasty solution.. Use the ugly #! style.
廉价而讨厌的解决方案.. 使用丑陋的 #! 风格。
To set it:
要设置它:
window.location.hash = '#!' + id;
To read it:
阅读它:
id = window.location.hash.replace(/^#!/, '');
Since it doesn't match and anchor or id in the page, it won't jump.
由于它与页面中的锚点或 id 不匹配,因此不会跳转。
回答by user706270
Why dont you get the current scroll position, put it in a variable then assign the hash and put the page scroll back to where it was:
为什么不获取当前滚动位置,将其放入变量中,然后分配散列并将页面滚动放回原来的位置:
var yScroll=document.body.scrollTop;
window.location.hash = id;
document.body.scrollTop=yScroll;
this should work
这应该有效
回答by aldemarcalazans
I used a combination of Attila Fulop (Lea Verou) solution for modern browsers and Gavin Brock solution for old browsers as follows:
我将 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;
}
As observed by Gavin Brock, to capture the id back you will have to treat the string (which in this case can have or not the "!") as follows:
正如 Gavin Brock 所观察到的,要捕获 id,您必须按如下方式处理字符串(在这种情况下可以有或没有“!”):
id = window.location.hash.replace(/^#!?/, '');
Before that, I tried a solution similar to the one proposed by user706270, but it did not work well with Internet Explorer: as its Javascript engine is not very fast, you can notice the scroll increase and decrease, which produces a nasty visual effect.
在此之前,我尝试了一个类似于user706270提出的解决方案,但它在Internet Explorer上运行不佳:由于其Javascript引擎不是很快,您可以注意到滚动增加和减少,这产生了令人讨厌的视觉效果。
回答by Mike Vallano
This solution worked for me.
这个解决方案对我有用。
The problem with setting location.hash
is that the page will jump to that id if it's found on the page.
设置的问题location.hash
在于,如果在页面上找到该 id,该页面将跳转到该 id。
The problem with window.history.pushState
is that it adds an entry to the history for each tab the user clicks. Then when the user clicks the back
button, they go to the previous tab. (this may or may not be what you want. it was not what I wanted).
问题window.history.pushState
在于它为用户单击的每个选项卡在历史记录中添加了一个条目。然后当用户单击back
按钮时,他们会转到上一个选项卡。(这可能是也可能不是你想要的。这不是我想要的)。
For me, replaceState
was the better option in that it only replaces the current history, so when the user clicks the back
button, they go to the previous page.
对我来说,这replaceState
是更好的选择,因为它只替换当前历史记录,因此当用户单击back
按钮时,他们会转到上一页。
$('#tab-selector').tabs({
activate: function(e, ui) {
window.history.replaceState(null, null, ui.newPanel.selector);
}
});
Check out the History API docson MDN.
查看MDN 上的History API 文档。
回答by Rohit Dhiman
This solution worked for me
这个解决方案对我有用
// 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');
And my full js code is
我的完整 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');
回答by Jon B
I'm not sure if you can alter the original element but how about switch from using the id attr to something else like data-id? Then just read the value of data-id for your hash value and it won't jump.
我不确定您是否可以更改原始元素,但是如何从使用 id attr 切换到诸如 data-id 之类的其他内容?然后只需为您的哈希值读取 data-id 的值,它就不会跳转。
回答by Andrew
When using laravel framework, I had some issues with using a route->back() function since it erased my hash. In order to keep my hash, I created a simple function:
使用 laravel 框架时,我在使用 route->back() 函数时遇到了一些问题,因为它删除了我的哈希。为了保持我的哈希,我创建了一个简单的函数:
$(function() {
if (localStorage.getItem("hash") ){
location.hash = localStorage.getItem("hash");
}
});
and I set it in my other JS function like this:
我将它设置在我的其他 JS 函数中,如下所示:
localStorage.setItem("hash", myvalue);
You can name your local storage values any way you like; mine named hash
.
您可以以任何您喜欢的方式命名您的本地存储值;我的名字叫hash
。
Therefore, if the hash is set on PAGE1 and then you navigate to PAGE2; the hash will be recreated on PAGE1 when you click Back on PAGE2.
因此,如果在 PAGE1 上设置了哈希,然后导航到 PAGE2;当您在 PAGE2 上单击返回时,将在 PAGE1 上重新创建哈希。