Javascript Onhashchange仅使用浏览器按钮

Javascript Onhashchange仅使用浏览器按钮,javascript,jquery,ajax,hashchange,Javascript,Jquery,Ajax,Hashchange,我遇到了这个问题(我正在使用jQuery,但不限于此): 我正在使用锚导航(#id)和Ajax请求的组合。为了让页面移动到位(使用锚导航)或获取信息(使用Ajax),我使用onhashchange事件 编辑:我有点打字错误。我忘了检查mouseDown标志是否为true,hashchange事件是否被触发,所以我添加了if语句 对于jQuery,它看起来是这样的:(当然,这段代码被包装在函数中,并在DOM加载时初始化,但这与问题无关) 为了确保只有支持onhashchange的浏览器才能读取代码

我遇到了这个问题(我正在使用jQuery,但不限于此):

我正在使用锚导航(#id)和Ajax请求的组合。为了让页面移动到位(使用锚导航)或获取信息(使用Ajax),我使用onhashchange事件

编辑:我有点打字错误。我忘了检查mouseDown标志是否为true,hashchange事件是否被触发,所以我添加了if语句

对于jQuery,它看起来是这样的:(当然,这段代码被包装在函数中,并在DOM加载时初始化,但这与问题无关)

为了确保只有支持onhashchange的浏览器才能读取代码,我将其封装为:


if ('onhashchange' in window) {
  $(window).bind('hashchange', function(e) { }
}

if ('onhashchange' in window) {
  $(window).bind('mousedown hashchange', function(e) { }
}

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
    }
  }
}

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
    }
  }
}
我的web应用程序是这样制作的,我只希望在点击浏览器中的后退/前进按钮时触发onhashchange事件。为此,我喜欢这样做:


if ('onhashchange' in window) {
  $(window).bind('hashchange', function(e) { }
}

if ('onhashchange' in window) {
  $(window).bind('mousedown hashchange', function(e) { }
}

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
    }
  }
}

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
    }
  }
}
现在,如果我在视口中单击,我将触发mousedown事件。如果触发mousedown事件,我知道我没有单击浏览器后退/前进按钮,我可以使用如下标志停止onhashchange事件:


if ('onhashchange' in window) {
  $(window).bind('hashchange', function(e) { }
}

if ('onhashchange' in window) {
  $(window).bind('mousedown hashchange', function(e) { }
}

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
    }
  }
}

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出现问题,因为无法将鼠标事件绑定到窗口对象(?)。IE永远不会“看到”mousedown事件

要解决这个IE问题我可以使用“clientY”属性。此属性在IE中的所有事件调用中传递,并告诉您鼠标的坐标。如果e.clientY小于0,则鼠标位于视口外,我将知道我通过单击浏览器后退/前进按钮触发了onhashchange。现在看起来是这样的:


if ('onhashchange' in window) {
  $(window).bind('hashchange', function(e) { }
}

if ('onhashchange' in window) {
  $(window).bind('mousedown hashchange', function(e) { }
}

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
    }
  }
}

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事件。这意味着客户端检查不再按预期工作

问题:

据我所知,onhashchange必须绑定到window对象。如果我想通过监听另一个事件来控制一个事件,那么所有事件都必须在同一个回调函数中处理

我怎样才能让它工作呢?

简单地说-

“我如何区分后退/前进按钮的按下与来自与DOM交互的导航”

您可能希望设置一个标志,以便在从代码更改URL的哈希部分时,设置该标志,忽略hashchange事件,然后取消设置该标志。在这种情况下,事件将被忽略(这是一种与您尝试执行的操作相反的解决方案)。显然,您希望将其包装到函数中

但是,一般来说,使用hashchange事件进行导航的应用程序通常会使用hashchange事件作为更改应用程序状态的手段。因此,只有一个入口点,您不需要区分事件是由浏览器导航还是由dom交互生成的。我可能会建议改变你的方法


我还要指出一个事实,即所有浏览器都可以支持历史记录(甚至使用iFrame hack的IE6和IE7)。请查看参考库以实现此目的:

我用过,效果很好

考虑在url中的“#”之后加上“!”,这样google就可以发现ajax页面

(“窗口”中的“onhashchange”)如果尚未定义,将始终返回false;如果已定义,则返回true。这并不意味着浏览器将实际在hashchange上执行代码,这类似于window.onload,它是未定义的,除非实际为其分配了一个函数,即使实际上所有浏览器都支持它。是的,我故意忽略了函数声明,因为我认为它与问题无关。绑定hashchange事件的函数在DOM加载时被调用。我并不特别喜欢使用插件(或者不是我自己编写的代码)。尤其是插件,它比我需要的做得更多。在这种情况下,我正在构建一个封闭的系统,这样谷歌就永远不会看到这些页面。不过还是谢谢你的链接。这是一个伟大的参考!该死,我就知道可以用更简短的方式来描述;)这就是问题所在,哈希部分从未从代码中设置。它是从默认链接行为设置的,并利用浏览器历史使用浏览器按钮来回导航。改变方法不是一种选择。我的解决方案一直运行良好,直到我必须实现keyDown事件。此外,我并没有提到这是一个GTIE7的目标解决方案,因为我们可以控制用户的一部分。所以IE6和IE7不会有任何问题。关于“更改应用程序的状态”。这个解决方案有点不同,因为它使用了动画锚导航和ajax调用的组合。如果只是ajax调用,这不会是一个问题。:)无论如何,我会给出一个相反的解决方案,看看我是否能找到一个新的角度来解决这个问题。谢谢。我不得不对代码的其他部分做一些修改,只剩下这个函数的hashchange事件。它不是很漂亮,但现在还可以用。