Onhashchange 仅适用于浏览器按钮
我遇到了这个问题(我正在使用 jQuery,但我不限于它):
我正在使用锚点导航 (#id) 和 Ajax 请求的组合。为了使页面移动到位(使用锚点导航)或获取信息(使用 Ajax),我使用 onhashchange 事件。
编辑:我有一个小错字。我忘记检查 mouseDown 标志是否为 true 以及 hashchange 事件是否被触发,所以我添加了 if 语句。
使用 jQuery,它看起来像这样:(当然,这段代码被包装在一个函数中,并在 DOM 加载时初始化,但这对问题来说并不重要)
$(window).bind('hashchange', function(e) { }
为了确保只有支持 onhashchange 的浏览器才能读取代码,我将其封装如下:
if ('onhashchange' in window) {
$(window).bind('hashchange', function(e) { }
}
My web应用程序的制作方式是,我只希望当我点击浏览器中的后退/前进按钮时触发 onhashchange 事件。为此,我这样做:
if ('onhashchange' in window) {
$(window).bind('mousedown hashchange', function(e) { }
}
现在,如果我在视口内单击,我将触发 mousedown 事件。如果触发 mousedown 事件,我知道我没有单击浏览器后退/前进按钮,并且我可以使用如下标志停止 onhashchange 事件:
var mouseDown = false;
if ('onhashchange' in window) {
$(window).bind('mousedown hashchange', function(e) {
if (e.type === 'mousedown') {
mouseDown = true;
}
if (mouseDown && e.type === 'hashchange') {
// if the mousedown event was triggered and when the haschange event triggers,
// we need to stop the hashchange event and restore the mouseDown flag
mouseDown = false;
e.stopPropagation();
}
if (!mouseDown && e.type === 'hashchange') {
// Do the onhashchange stuff here
}
}
}
这会导致 IE 出现问题,因为它会让您感到困惑无法将鼠标事件绑定到窗口对象(?)。 IE 永远不会“看到” mousedown 事件。
要解决此 IE 问题,我可以采用“clientY”属性。该属性会在 IE 中的所有事件调用中传递,并告诉您鼠标的坐标。如果 e.clientY 小于 0,则鼠标位于视口之外,我将知道我通过单击浏览器后退/前进按钮触发了 onhashchange。现在看起来像这样:
var mouseDown = false;
if ('onhashchange' in window) {
$(window).bind('mousedown hashchange', function(e) {
// IE: Use e.clientY to check if the mouse position was within the viewport (i.e. not a nagative value for Y)
// !IE: Use e.type
if (e.type === 'mousedown' || e.clientY > 0 ) {
mouseDown = true;
}
if (mouseDown && e.type === 'hashchange') {
// if the mousedown event was triggered and when the haschange event triggers,
// we need to stop the hashchange event and restore the mouseDown flag
mouseDown = false;
e.stopPropagation();
}
if (!mouseDown && e.type === 'hashchange') {
// Do the onhashchange stuff here
}
}
}
这个解决方案一直很有效,直到我不得不添加对使用键盘上的箭头进行导航的支持。现在,鼠标位于屏幕上的哪个位置并不重要。只要 IE 窗口处于“活动”状态,监听键盘输入的 keydown 事件就会在敲击键盘时触发。这意味着 clientY 检查不再按预期工作。
问题:
据我所知,onhashchange必须绑定到window对象。如果我希望能够通过监听另一个事件来控制一个事件,则所有事件都必须在同一回调函数中处理。
我怎样才能让它发挥作用?
I've got this issue (I'm using jQuery but I'm not restricted to it):
I'm using a combo of Anchor navigation (#id) and Ajax requests. To get the pages to move into place (using anchor navigation) or to fetch information (using Ajax), I use the onhashchange event.
EDIT: I had a little typo. I forgot to check if the mouseDown flag was true and the hashchange event was triggered so I added that if statement.
with jQuery it looks like this: (of course this code is wrapped in a function and initialized on DOM load but it doesn't matter for the question)
$(window).bind('hashchange', function(e) { }
To ensure only browsers supporting the onhashchange reads the code I encapsulate it like this:
if ('onhashchange' in window) {
$(window).bind('hashchange', function(e) { }
}
My web app is made in such way that I only want the onhashchange event to trigger when I hit the back/forward buttons in the browser. To do that I do like this:
if ('onhashchange' in window) {
$(window).bind('mousedown hashchange', function(e) { }
}
Now if I click within the viewport I will trigger the mousedown event. If the mousedown event is triggered I know that I didn't click the browser back/forward buttons and I can stop the onhashchange event using a flag like this:
var mouseDown = false;
if ('onhashchange' in window) {
$(window).bind('mousedown hashchange', function(e) {
if (e.type === 'mousedown') {
mouseDown = true;
}
if (mouseDown && e.type === 'hashchange') {
// if the mousedown event was triggered and when the haschange event triggers,
// we need to stop the hashchange event and restore the mouseDown flag
mouseDown = false;
e.stopPropagation();
}
if (!mouseDown && e.type === 'hashchange') {
// Do the onhashchange stuff here
}
}
}
This causes a problem for IE since it seams you cannot bind mouse events to the window object (?). IE will never "see" the mousedown event.
To solve this IE issue I can take the "clientY" property. This property is passed in all event calls in IE and tells you the coordinates of the mouse. If e.clientY is less then 0, the mouse is outside the viewport and I will know that I triggered the onhashchange by clicking the browser back/forward buttons. It now looks like this:
var mouseDown = false;
if ('onhashchange' in window) {
$(window).bind('mousedown hashchange', function(e) {
// IE: Use e.clientY to check if the mouse position was within the viewport (i.e. not a nagative value for Y)
// !IE: Use e.type
if (e.type === 'mousedown' || e.clientY > 0 ) {
mouseDown = true;
}
if (mouseDown && e.type === 'hashchange') {
// if the mousedown event was triggered and when the haschange event triggers,
// we need to stop the hashchange event and restore the mouseDown flag
mouseDown = false;
e.stopPropagation();
}
if (!mouseDown && e.type === 'hashchange') {
// Do the onhashchange stuff here
}
}
}
This solution was working like a charm until I had to add support for navigating with the arrows on the keyboard. Now it doesn't matter where on the screen the mouse is. As long as the IE window is "active", the keydown event listening for keyboard input triggers when hitting the keyboard. This means that the clientY check does not work anymore as intended.
The Problem:
As far as I know, the onhashchange must be bound to the window object. All events must be processed within the same callback function if I want to be able to control one event by listening for another.
How can I get this to work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
所以,简单地说
,“如何区分后退/前进按钮按下与来自与 DOM 交互的导航”。
您可能需要一个标志,这样当您从代码更改 URL 的哈希部分时,您可以设置此标志,忽略 hashchange 事件,然后取消设置该标志。在这种情况下,该事件将被忽略(一种与您尝试执行的操作相反的解决方案)。您显然希望将其包装在一个函数中。
然而,一般来说,使用 hashchange 事件进行导航的应用程序通常会使用 hashchange 事件作为更改应用程序状态的方法。因此,只有一个入口点,您无需区分事件是由浏览器导航生成还是由 dom 交互生成。我可能会建议改变你的方法。
我还想向您指出这样一个事实:所有浏览器都可以支持历史记录(甚至使用 iFrame hack 的 IE6 和 IE7)。看一下 jQuery 历史记录插件
So, simply put-
"how do I distinguish between a back/forward button press vs. navigation coming from interacting with the DOM".
You may want to have a flag such that when you are changing the hash part of the URL from code, you set this flag, ignore the hashchange event, then unset the flag. In which case the event will be ignored ( a kind of reverse solution as to what you're trying to do). You'd obviously want to wrap this in a function.
In general however, applications that use the hashchange event for navigation will often use the hashchange event as a means for changing the state of the application. Therefore, there is only one entry point and you do not need to distinguish between whether the event is generated by browser navigation vs. dom interaction. I'd probably recommend changing your approach.
I'd also point you to the fact that history can be supported across all browsers (even IE6 and IE7 using an iFrame hack). Take a look at the jQuery history plugin
实现此目的的参考库:
http://benalman.com/projects/jquery-bbq-plugin/
我用过它而且效果很好
考虑加上“!” url 中的“#”之后,以便 google 可以发现 ajax 页面
http://code.google.com/web/ajaxcrawling/docs/getting -started.html
The reference library to achieve this:
http://benalman.com/projects/jquery-bbq-plugin/
I used it and it works great
Think about putting "!" after "#" in the url, so that google can discover the ajax pages
http://code.google.com/web/ajaxcrawling/docs/getting-started.html