如何在JavaScript中判断页面是否跳转到锚点(#)?

11

我有一些JavaScript代码,可能出现在许多不同的页面上。有时这些页面是通过包含锚点引用(例如#comment-100)的URL访问的。在这种情况下,我希望JavaScript延迟执行,直到窗口跳转后再执行。目前我只是使用延迟,但那相当于一个hackish的解决方案,而且显然并不适用于所有情况。我似乎找不到任何对应于窗口“跳跃”的DOM事件。

除了简单的延迟之外,我想到的唯一解决方案是让JS查找URL中的锚点,并在找到锚点时监听scrollTop的更改。但是这似乎存在漏洞,并且我并不确定我的脚本是否始终会在滚动发生之前被触发,因此只有在用户手动滚动页面时它才会运行。总之,我不太喜欢这个解决方案,并希望有更多基于事件驱动的解决方案。你有什么建议吗?

编辑以澄清:

我不是要检测哈希值的更改。请看以下示例:

  1. 页面index.php包含指向post.php#comment-1的链接
  2. 用户单击链接post.php#comment-1
  3. post.php#comment-1加载
  4. $(document).ready触发
  5. 不久后,浏览器将滚动到#comment-1

我要可靠地检测步骤5何时发生。


$(document).ready() 触发过早? - Peter Ajtai
3个回答

4
你可以在现代浏览器中检查window.onhashchange。如果你想要跨浏览器兼容性,可以查看http://benalman.com/projects/jquery-hashchange-plugin/
此页面还提供有关window.onhashchange的更多信息。
编辑:你基本上需要用类似的链接约定替换所有锚点名称,然后使用.scrollTo来处理滚动:
$(document).ready(function () {
  // replace # with #_ in all links containing #
  $('a[href*=#]').each(function () {
      $(this).attr('href', $(this).attr('href').replace('#', '#_'));
  });

  // scrollTo if #_ found
  hashname = window.location.hash.replace('#_', '');
  // find element to scroll to (<a name=""> or anything with particular id)
  elem = $('a[name="' + hashname + '"],#' + hashname);

  if(elem) {
       $(document).scrollTo(elem, 800,{onAfter:function(){
        //put after scroll code here }});
  }
});

请参见jQuery:在调用URL时滚动到锚点,替换浏览器行为获取更多信息。


2
@bryan - 问题不在于检测哈希变化,而在于检查在使用哈希的情况下,窗口是否已经滚动到正确的位置。 - Peter Ajtai
我需要查看一下.scrollTo是否能够处理初始页面加载时URL中有锚点的情况。我认为.scrollTo仅仅处理在当前页面内点击锚点链接时的滚动。 - Aaron
不幸的是,.scrollTo 似乎无法处理这种情况,尽管我很愿意被证明是错误的! - Aaron
@Aaron:实际上,$.scrollTo 可以与跨页面链接一起使用。我编辑了一些代码在我的答案中向你展示我所说的内容。 - bryan.taylor
很好。在问题中,信息的多少总是需要平衡的。我试图提出一个非常具体的问题,关于如何检测页面跳转,但不确定讨论会引向何方。 - Aaron
显示剩余3条评论

1

看起来你可以使用window.onscroll。我刚刚测试了这段代码:

<a name="end" />
<script type="text/javascript">
    window.onscroll = function (e) {
        alert("scrolled");
}
</script>

看起来是有效的。

编辑:嗯,在IE8中不起作用。但在Firefox和Chrome中都可以工作。

编辑:jQuery有一个{{link1:.scroll()}}处理程序,但它在IE上滚动之前触发,并且似乎无法在Chrome或Firefox上工作。


2
@Gilsham - 如果窗口因其他原因滚动了呢? - Peter Ajtai
是的,我猜你在运行代码后必须解除绑定。 只需在警报后添加一行 window.onscroll = null;,它看起来就很好。 - Gilsham
页面加载后,您还可以检查 window.pageYOffset,如果它大于 0,则表示页面已向下滚动。 - Gilsham
问题在于如何知道何时检查pageYOffset。文档准备就绪会太早触发。 - Aaron
jQuery的.scroll()处理程序可能是我见过的最可行的解决方案。我需要进行一些测试。我担心会出现竞争条件(我不确定在每个浏览器的每种情况下文档准备好是否在滚动之前触发),但我可能可以拼凑出一些东西。 - Aaron
我会给Gilsham答案,因为他回答了我实际问题最接近的答案,并概述了我将尝试使用的一般方法。话虽如此,Bryan提供了一些有用的提示,可能为其他发现自己处于类似情况的人提供了最有用的信息。 - Aaron

0
要检测元素何时出现在屏幕上,可以使用appear插件:
$('#comment-1').appear(function() {
  $(this).text('scrolled');
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接