ChatGPT解决这个技术问题 Extra ChatGPT

单击触发 JavaScript 的链接时,如何阻止网页滚动到顶部?

当我有一个与 jQuery 或 JavaScript 事件关联的链接时,例如:

<a href="#">My Link</a>

如何防止页面滚动到顶部?当我从锚点中删除 href 属性时,页面不会滚动到顶部,但链接似乎不可点击。


C
Community

您需要防止发生单击事件的默认操作(即导航到链接目标)。

有两种方法可以做到这一点。

选项 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:返回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 年):stackoverflow.com/a/11246131/216941
在这种情况下,Achilles 这样做只是因为他希望链接显示为可点击,而他根本不需要使用 href="#"。有关更多信息,请参阅我的答案。
很好地添加到这个解决方案@achecopar,“#!”使用 onclick 执行函数的 add 可防止滚动行为。
C
Community

您可以将 href 设置为 #! 而不是 #

例如,

<a href="#!">Link</a>

单击时不会进行任何滚动。

当心!这仍然会在点击时向浏览器的历史记录添加一个条目,这意味着在点击您的链接后,用户的后退按钮不会将他们带到他们之前所在的页面。出于这个原因,使用 .preventDefault() 方法可能会更好,或者将两者结合使用。

这是一个 Fiddle 来说明这一点(只需向下滚动浏览器,直到出现滚动条):
http://jsfiddle.net/9dEG7/

对于规范书呆子 - 为什么这样有效:

此行为在 Navigating to a fragment identifier 部分下的 HTML5 规范中指定。 href 为 "#" 的链接导致文档滚动到顶部的原因是,此行为被明确指定为处理空片段标识符的方式:

2. 如果 fragid 是空字符串,那么文档的指示部分是文档的顶部

使用 "#!" 的 href 只是因为它避免了此规则。感叹号没有什么神奇之处 - 它只是一个方便的片段标识符,因为它与典型的 fragid 明显不同,并且不太可能匹配页面上元素的 idname。事实上,我们几乎可以在哈希之后放置任何东西;唯一不能满足要求的是空字符串、单词“top”或与页面上元素的 nameid 属性匹配的字符串。

更准确地说,我们只需要一个片段标识符,它将导致我们进入以下算法中的第 8 步,以便从片段中确定文档的指示部分:

将 URL 解析器算法应用于 URL,并让 fragid 成为解析后的 URL 的片段组件。如果 fragid 是空字符串,则文档的指示部分是文档的顶部;在这里停止算法。设脆弱字节是百分比解码脆弱的结果。设解码的脆弱是对脆弱字节应用 UTF-8 解码器算法的结果。如果 UTF-8 解码器发出解码器错误,则中止解码器并跳转到标记为 no decoded fragid 的步骤。如果 DOM 中有一个元素的 ID 与 decoded fragid 完全相同,那么树顺序中的第一个这样的元素就是文档的指示部分;在这里停止算法。 No decoded fragid:如果 DOM 中有一个 a 元素的 name 属性的值正好等于 fragid(未解码的 fragid),那么树顺序中的第一个这样的元素就是文档的指示部分;在这里停止算法。如果 fragid 是字符串 top 的不区分大小写的 ASCII 匹配,则文档的指示部分是文档的开头;在这里停止算法。否则,文档中没有指定的部分。

只要我们点击第 8 步并且文档中没有指定的部分,以下规则就会起作用:

如果没有指定的部分......那么用户代理必须什么都不做。

这就是浏览器不滚动的原因。


没关系,如果你把'!或任何其他值,只要 id 不是 DOM 的一部分。
在曾经是这种方法的倡导者之后,我已经做了一个 180 并反对它。注意:这样的链接仍然会改变页面 URL,导致浏览器历史记录中出现额外的条目,并导致“后退”按钮简单地从 URL 中删除片段,而不是按照用户的期望进行。 因此,这个解决方案本身虽然回答了所提出的问题,但通常不是在点击处理程序中使用 preventDefault() 的理想替代方案 - 令人遗憾的是。
为什么不使用 href="javascript:;"反而?据我所知,它不会改变浏览器的历史。在我的答案上发布了它。
这应该是公认的答案
p
phreeskier

一种简单的方法是利用此代码:

<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 方法没有失败时,最后一个解决方案将避免滚动跳转问题。


a
achecopar

你应该改变

<a href="#">My Link</a>

<a href="javascript:;">My Link</a>

这样,当点击链接时,页面不会滚动到顶部。这比使用 href="#" 然后阻止默认事件运行更干净。

我对 this question 的第一个答案有充分的理由,例如如果被调用的函数抛出错误,return false; 将不会执行,或者您可以将 return false; 添加到 doSomething() 函数然后忘记使用return doSomething();


谢谢!完全按照我的预期工作。
不客气!
M
Mark Amery

从您正在调用的代码中返回 false 将起作用,并且在许多情况下是首选方法,但您也可以这样做

<a href="javascript:;">Link Title</a>

当谈到 SEO 时,它实际上取决于您的链接将用于什么。如果您要实际使用它来链接到其他一些内容,那么我同意理想情况下您会在这里想要一些有意义的东西,但是如果您出于功能目的使用该链接,可能就像 Stack Overflow 对帖子工具栏所做的那样(粗体、斜体、超链接等)那么它可能并不重要。


m
mikeluby

尝试这个:

<a href="#" onclick="return false;">My Link</a>

d
dazbradbury

如果您可以简单地更改 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() 行之后,否则您将永远无法到达第二行?
Q
Quentin

首先链接到比页面顶部更明智的内容。然后取消默认事件。

参见 pragmatic progressive enhancement 的规则 2。


这也使您的网站对 SEO 更加友好。
e
efirat

此外,您可以在 onclick 属性中使用 event.preventDefault 。

<a href="#" onclick="event.preventDefault(); doSmth();">doSmth</a>

无需编写额外的点击事件。


d
doug

对于Bootstrap 3 for collapse,如果你没有在anchor上指定data-target,而是依靠href来确定目标,那么该事件将被阻止。如果您使用数据目标,您需要自己阻止该事件。

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

u
user2436792

你也可以像这样简单地写:-

<a href="#!" onclick="function()">Delete User</a>

b
buddhi weerasinghe

调用该函数时,请遵循 return false 示例:

<input  type="submit" value="Add" onclick="addNewPayment();return false;">

D
Damini

创建一个包含两个链接的页面——一个在顶部,一个在底部。单击顶部链接时,页面必须向下滚动到存在底部链接的页面底部。单击底部链接时,页面必须向上滚动到页面顶部。


M
Martijn Pieters
<a onclick="yourfunction()">

这会很好。无需添加 href="#"


S
Scott Phillips

你可能想检查你的 CSS。在此处的示例中:https://css-tricks.com/the-checkbox-hack/position: absolute; top: -9999px;。这在 Chrome 上尤其愚蠢,因为 onclick="whatever" 仍会跳转到被点击元素的绝对位置。

display: none; 删除 position: absolute; top: -9999px; 可能会有所帮助。


P
Procrastinator

event.preventDefault() 将停止滚动,但也不会将链接状态更改为 visited (color),这是我需要的。 “迟到 3 年”的解决方案还不算晚,而且消除了不可预见的副作用。我创建的 href 在一个循环中(由“i”索引)“#i!”,其中 i 是包含锚标记文本的数组的索引。奇迹般有效。 (只是 #i 也可以,除非我将其他 id 设置为 i)。

虽然我想使用 `href='javascript:function()'` 方法,但这会增加 11 个字节 (javascript:) 加上函数名的字节以及页面大小的参数。将其乘以 1000+ 的 href,即 16kb+ 添加到页面大小。 (是的,分页会有所帮助,但对用户没有帮助)。所以也许在不同的情况下,我会使用 javascript: 解决方案。