单击触发 JavaScript 的链接时,如何阻止网页滚动到顶部?
Posted
技术标签:
【中文标题】单击触发 JavaScript 的链接时,如何阻止网页滚动到顶部?【英文标题】:How do I stop a web page from scrolling to the top when a link is clicked that triggers JavaScript? 【发布时间】:2010-12-08 18:51:06 【问题描述】:当我有一个与 jQuery 或 javascript 事件相关联的链接时,例如:
<a href="#">My Link</a>
如何防止页面滚动到顶部?当我从锚点中删除 href 属性时,页面不会滚动到顶部,但链接似乎不可点击。
【问题讨论】:
【参考方案1】:您需要防止发生单击事件的默认操作(即导航到链接目标)。
有两种方法可以做到这一点。
选项 1:event.preventDefault()
调用传递给处理程序的事件对象的.preventDefault()
方法。如果您使用 jQuery 绑定您的处理程序,则该事件将是 jQuery.Event
的一个实例,它将是 .preventDefault()
的 jQuery 版本。如果您使用addEventListener
绑定您的处理程序,它将是Event
和.preventDefault()
的原始DOM 版本。无论哪种方式都可以满足您的需求。
例子:
$('#ma_link').click(function($e)
$e.preventDefault();
doSomething();
);
document.getElementById('#ma_link').addEventListener('click', function (e)
e.preventDefault();
doSomething();
)
选项 2:return false;
In jQuery:
从事件处理程序返回 false 将自动调用 event.stopPropagation() 和 event.preventDefault()
因此,使用 jQuery,您也可以使用这种方法来防止默认链接行为:
$('#ma_link').click(function(e)
doSomething();
return false;
);
如果您使用原始 DOM 事件,这也适用于现代浏览器,因为 html 5 规范规定了这种行为。但是,旧版本的规范没有,所以如果您需要与旧浏览器的最大兼容性,您应该明确调用.preventDefault()
。有关规格详细信息,请参阅event.preventDefault() vs. return false (no jQuery)。
【讨论】:
发布了一个不需要附加点击处理程序的解决方案(3 年后):***.com/a/11246131/216941 在这种情况下,Achilles 这样做只是因为他希望链接显示为可点击,而他根本不需要使用 href="#"。有关更多信息,请参阅我的答案。【参考方案2】:您可以将 href 设置为 #!
而不是 #
例如,
<a href="#!">Link</a>
点击时不会进行任何滚动。
当心!这仍然会在点击时向浏览器的历史记录添加一个条目,这意味着在点击您的链接后,用户的后退按钮不会将他们带到他们之前所在的页面。出于这个原因,使用.preventDefault()
方法可能会更好,或者将两者结合使用。
这里有一个 Fiddle 来说明这一点(只需向下滚动浏览器,直到出现滚动条):http://jsfiddle.net/9dEG7/
对于规范书呆子 - 为什么会这样:
此行为在 HTML5 规范中的 Navigating to a fragment identifier 部分下指定。带有"#"
的href 的链接导致文档滚动到顶部的原因是这种行为被明确指定为处理空片段标识符的方式:
2。如果
fragid
是空字符串,则文档的指示部分是文档的顶部
使用"#!"
的href 只是因为它避免了这条规则。感叹号没有什么神奇之处——它只是一个方便的片段标识符,因为它与典型的 fragid 明显不同,并且不太可能匹配页面上元素的id
或name
。事实上,我们几乎可以在哈希之后放置任何东西;唯一不能满足要求的是空字符串、单词“top”或与页面上元素的name
或id
属性匹配的字符串。
更准确地说,我们只需要一个片段标识符,它将导致我们进入以下算法中的第 8 步,以从片段中确定文档的指示部分:
将 URL 解析器算法应用于 URL,并让 fragid 成为解析后的 URL 的片段组件。
如果
fragid
是空字符串,则文档的指示部分是文档的顶部;在这里停止算法。让
fragid bytes
成为百分比解码的结果fragid
。让
decoded fragid
成为将 UTF-8 解码器算法应用于fragid bytes
的结果。如果 UTF-8 解码器发出解码器错误,则中止解码器并转至标记为no decoded fragid
的步骤。如果 DOM 中有一个元素的 ID 正好等于
decoded fragid
,那么树顺序中的第一个这样的元素就是文档的指示部分;在这里停止算法。没有解码的脆弱:如果DOM中有一个a元素的name属性的值正好等于
fragid
(不是@ 987654343@),那么树顺序中的第一个这样的元素是文档的指示部分;在这里停止算法。如果fragid 是字符串
top
的不区分大小写的ASCII 匹配,则文档的指示部分是文档的顶部;在这里停止算法。否则,文档中没有指定的部分。
只要我们点击第 8 步并且文档中没有指定的部分,下面的规则就会起作用:
如果没有指定的部分......那么用户代理必须什么都不做。
这就是浏览器不滚动的原因。
【讨论】:
如果你放 '!' 也没关系或任何其他值,只要 id 不是 DOM 的一部分。 曾经是这种方法的倡导者,后来我做了180并反对它。注意:这样的链接仍然会改变页面 URL,导致浏览器历史记录中出现额外的条目,并导致“后退”按钮简单地从 URL 中删除片段,而不是按照用户的期望进行。 因此,这个解决方案本身,虽然按要求回答问题,但通常不是在点击处理程序中使用preventDefault()
的理想替代方案 - 很遗憾。
为什么不使用 href="javascript:;"反而?据我所知,它不会改变浏览器的历史。在我的答案上发布了它。
这应该是公认的答案【参考方案3】:
一种简单的方法是利用此代码:
<a href="javascript:void(0);">Link Title</a>
这种方法不会强制刷新页面,因此滚动条会保持原位。此外,它还允许您以编程方式更改 onclick 事件并使用 jQuery 处理客户端事件绑定。
由于这些原因,上述解决方案优于:
<a href="javascript:myClickHandler();">Link Title</a>
<a href="#" onclick="myClickHandler(); return false;">Link Title</a>
当且仅当 myClickHandler 方法没有失败时,最后一个解决方案将避免滚动跳转问题。
【讨论】:
【参考方案4】:你应该改变
<a href="#">My Link</a>
到
<a href="javascript:;">My Link</a>
这样,当点击链接时,页面不会滚动到顶部。这比使用 href="#" 然后阻止默认事件运行更干净。
在this question 的第一个答案中我有充分的理由,例如如果被调用的函数抛出错误,return false;
将不会执行,或者您可以将 return false;
添加到 doSomething()
函数然后忘记使用return doSomething();
【讨论】:
谢谢!完全符合我的预期。 不客气!【参考方案5】:从您调用的代码中返回 false 将起作用,并且在许多情况下是首选方法,但您也可以这样做
<a href="javascript:;">Link Title</a>
当谈到 SEO 时,它实际上取决于您的链接将用于什么。如果您要实际使用它来链接到其他一些内容,那么我同意理想情况下您会在这里想要一些有意义的东西,但是如果您出于功能目的使用该链接,可能就像 Stack Overflow 对帖子工具栏所做的那样(粗体、斜体、超链接等)那么它可能并不重要。
【讨论】:
【参考方案6】:试试这个:
<a href="#" onclick="return false;">My Link</a>
【讨论】:
【参考方案7】:如果您可以简单地更改href
的值,您应该使用:
<a href="javascript:void(0);">Link Title</a>
我刚刚想出的另一个巧妙的解决方案是使用 jQuery 来阻止点击动作发生并导致页面滚动,但仅适用于 href="#"
链接。
<script type="text/javascript">
/* Stop page jumping when links are pressed */
$('a[href="#"]').live("click", function(e)
return false; // prevent default click action from happening!
e.preventDefault(); // same thing as above
);
</script>
【讨论】:
return false
肯定应该在preventDefault()
行之后,否则您将永远无法到达第二行?【参考方案8】:
首先链接到比页面顶部更明智的内容。然后取消默认事件。
参见pragmatic progressive enhancement 的规则 2。
【讨论】:
这也让你的网站对 SEO 更友好。【参考方案9】:另外,您可以在 onclick 属性中使用 event.preventDefault。
<a href="#" onclick="event.preventDefault(); doSmth();">doSmth</a>
无需编写额外的点击事件。
【讨论】:
【参考方案10】:对于Bootstrap 3 for collapse,如果你没有在anchor上指定data-target,而是依靠href来确定target,那么该事件将被阻止。如果您使用数据目标,则需要自己阻止该事件。
<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#demo">Collapse This</button>
<div id="demo" class="collapse">
<p>Lorem ipsum dolor sit amet</p>
</div>
【讨论】:
【参考方案11】:你也可以这样写:-
<a href="#!" onclick="function()">Delete User</a>
【讨论】:
【参考方案12】:调用函数时,跟在return false
后面
示例:
<input type="submit" value="Add" onclick="addNewPayment();return false;">
【讨论】:
【参考方案13】:创建一个包含两个链接的页面——一个在顶部,一个在底部。单击顶部链接时,页面必须向下滚动到存在底部链接的页面底部。单击底部链接时,页面必须向上滚动到页面顶部。
【讨论】:
【参考方案14】:<a onclick="yourfunction()">
这会很好用。无需添加 href="#"
【讨论】:
【参考方案15】:您可能需要检查您的 CSS。在此处的示例中:https://css-tricks.com/the-checkbox-hack/ 有 position: absolute; top: -9999px;
。这在 Chrome 上尤其愚蠢,因为 onclick="whatever"
仍然会跳转到被点击元素的绝对位置。
删除position: absolute; top: -9999px;
,因为display: none;
可能会有所帮助。
【讨论】:
以上是关于单击触发 JavaScript 的链接时,如何阻止网页滚动到顶部?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用ctrl +单击阻止javascript阻止打开新选项卡