JavaScript链接中应该使用哪个“href”值,"#"还是"javascript:void(0)"?

4419

以下是两种用于运行JavaScript代码的链接构建方法。从功能、页面加载速度、验证目的等方面来看,哪种更好?

function myJsFunc() {
    alert("myJsFunc");
}
<a href="#" onclick="myJsFunc();">Run JavaScript Code</a>

或者

function myJsFunc() {
    alert("myJsFunc");
}
 <a href="javascript:void(0)" onclick="myJsFunc();">Run JavaScript Code</a>


14
为什么想要按钮时要使用链接?这样就不会出现伪协议的问题。 - RobG
2
验证目的 - 啊,这应该是一个红旗,表明这个问题已经过时了。现在没有人再关心验证或者网络标准了。曾经有一个短暂的时期,它很重要,事情看起来很光明,但是现在,每个人都随意做自己想做的事情(咳咳YouTube咳咳),浏览器也像90年代的IE一样适应他们。 - Synetech
不要使用链接,如果你真的必须使用链接,请使用一个样式为链接的span。没有需要烦恼的href。而且为什么使用void(0),当void 0即可? - RobG
56个回答

2304

我使用javascript:void(0)

原因有三。鼓励开发团队使用#最终会导致一些人使用此函数的返回值,如下所述:

function doSomething() {
    //Some code
    return false;
}

但是他们忘记在onclick中使用 return doSomething(),而只是使用 doSomething()

避免使用 # 的第二个原因是如果被调用的函数抛出错误,最后的 return false; 将不会执行。因此开发人员还必须记住适当地处理任何错误。

第三个原因是有些情况下会动态地分配 onclick 事件属性。我更喜欢能够调用一个函数或动态地分配它,而不必专门为一种附加方法编写函数。因此,我的 HTML 标记中的 onclick(或任何其他东西)看起来像这样:

onclick="someFunc.call(this)"

onclick="someFunc.apply(this, arguments)"

使用 javascript:void(0) 可以避免上述所有问题,我没有发现任何负面影响的例子。

因此,如果你是一个独立开发者,那么你可以自己做出选择,但如果你作为一个团队工作,你必须明确说明:

使用 href="#",确保 onclick 总是在结尾处包含 return false; ,被调用的任何函数都不会抛出错误,如果你动态地将一个函数附加到 onclick 属性上,也要确保它不会抛出错误,并返回 false

或者

使用 href="javascript:void(0)"

显然,第二种方法更容易交流。


172
快进到2013年:javascript:void(0)在启用CSP的HTTPS页面上违反内容安全策略。一个选项是在处理器中使用href='#'event.preventDefault(),但我不太喜欢这种方法。也许你可以建立一种约定来使用href='#void',并确保页面上没有任何元素的id为"void"。这样,单击指向不存在的锚点的链接将不会滚动页面。 - jakub.g
35
您可以使用"#",然后绑定一个点击事件到所有链接的href属性值为"#"的链接上。在jQuery中,可以这样实现:$('a[href="#"]').click(function(e) { e.preventDefault ? e.preventDefault() : e.returnValue = false; }); - Nathan
6
即使使用 #void,浏览器仍会添加一条历史记录。另一种方法是使用返回 HTTP 状态码为 204 的资源的 URL(仍然使用 preventDefault - 204 只是备用方案)。 - CherryDT
@s3c 回车键按下已经触发了点击事件,那么最后一个监听器还有必要吗? - Nathan
6
@HPWD 这是“船运崇拜编程”(cargo cult programming)的表现。 void 是一个操作符而不是函数。它应该是 void 0void(0) 中的括号没有任何作用。void() 就像 return(); 一样无效,因为 () 不是有效的一元表达式。 - Sebastian Simon
显示剩余5条评论

1411

两者都不行。

如果可以使用有意义的实际URL,请将其用作HREF。如果某人通过中键单击您的链接以打开新标签页,或者他们禁用了JavaScript,则onclick不会触发。

如果不可能,那么您至少应该使用JavaScript将锚点标签注入文档,并使用适当的click事件处理程序。

我知道这并不总是可能的,但在我看来,在开发任何公共网站时都应该努力达到这一点。

请查看不显眼的JavaScript渐进增强(均出自维基百科)。


50
如果不可能的话,那么请使用一个按钮代替。这就是这个答案应该有的结尾。 - Sebastian Simon
如果我们使用按钮,我们的可爱用户如何在他们闪亮的智能手机上打开新标签页中的href呢? - mohamed tebry
6
@mohamedtebry,您没有理解问题的重点:“建立一个仅旨在运行JavaScript代码的链接”。问题在于将链接用作按钮时,没有href来打开链接。 - RobG
@SebastianSimon Bootstrap 下拉菜单采用锚点结构进行样式设置。有时需要使用锚点 https://getbootstrap.com/docs/5.3/components/dropdowns/#single-button - Cemstrian

808

五年前,使用包含 onclick 属性的链接或其他任何内容 - 是可以接受的,但现在它可能是一种不好的实践。以下是原因:

  1. 它促进了粗暴的JavaScript实践 - 这已经被证明很难维护和扩展。有关此更多信息,请参见 Unobtrusive JavaScript

  2. 你要花费大量时间编写过于详细的代码 - 这对你的代码库几乎没有任何益处。

  3. 现在有更好、更简单、更可维护和可扩展的方法来实现所需的结果。

不显眼的JavaScript方式

根本不需要 href 属性!任何良好的CSS重置都会处理缺少默认光标样式的问题,所以这不是问题。然后使用优雅而不显眼的最佳实践来附加您的JavaScript功能 - 当您开始开发需要将逻辑拆分为黑箱组件和模板的大型JavaScript应用程序时,这种方式更可维护,因为您的JavaScript逻辑留在JavaScript中,而不是在您的标记中。有关此更多信息,请参见 大型JavaScript应用程序架构

简单的代码示例

// Cancel click event
$('.cancel-action').click(function(){
    alert('Cancel action occurs!');
});

// Hover shim for Internet Explorer 6 and Internet Explorer 7.
$(document.body).on('hover','a',function(){
    $(this).toggleClass('hover');
});
a { cursor: pointer; color: blue; }
a:hover,a.hover { text-decoration: underline; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a class="cancel-action">Cancel this action</a>

一个黑盒子的Backbone.js示例

有关可扩展、黑盒子、Backbone.js 组件示例 - 请参见此处工作的 JSFiddle 示例。请注意,我们如何利用不显眼的 JavaScript 实践,在极少量代码中拥有可以在页面上多次重复使用的组件,而不会出现副作用或不同组件实例之间的冲突。了不起!

注意事项

  • 省略 a 元素上的 href 属性将导致通过 tab 键导航无法访问该元素。如果您希望这些元素可以通过 tab 键访问,则可以设置 tabindex 属性,或者使用 button 元素。如在 Tracker1's answer 中提到的那样,您可以轻松地将 button 元素样式设置为普通链接样式。

  • 省略 a 元素上的 href 属性将导致 Internet Explorer 6Internet Explorer 7 无法使用 a:hover 样式,因此我们添加了一个简单的 JavaScript shim 来通过 a.hover 实现这一点。如果您没有 href 属性并且没有优雅地降级,那么您的链接就不起作用了 - 您将有更大的问题需要担心。

  • 如果您希望在 JavaScript 禁用时仍然能够使用您的操作,则使用具有指向某些 URL 的 href 属性的 a 元素,该 URL 将手动执行操作而不是通过 Ajax 请求或其他方式执行操作应该成为前进的方式。如果您这样做,则要确保在点击调用时对您的事件执行 event.preventDefault(),以确保单击按钮时它不会跟随链接。这个选项称为优雅地降级。


2
不错的回答,但是如果移除jQuery依赖会更好。;-) - RobG
传递一个参数给最终的JS方法怎么样?这是可能的吗? - DoomerDGR8

358

'#' 会将用户带回页面顶部,因此我通常会选择 void(0)

javascript:; 也像 javascript:void(0); 一样行为。


72
避免这种情况的方法是在onclick事件处理程序中返回false。 - Guvante
39
在事件处理程序中返回false并不能避免JavaScript代码执行失败。 - Quentin
34
使用“#someNonExistantAnchorName”很好,因为它没有跳转的目标。 - scunliffe
28
如果您有一个基础 href,那么 ##something 将带您到该锚点在 基础 href 页面上的位置,而不是当前页面。 - Abhi Beckert
15
Shebang (#!) 可以实现功能,但这绝对是不好的做法。 - Neel
显示剩余2条评论

350

我真诚地建议都不要使用。我会使用一个样式化的<button></button>元素实现这种行为。

button.link {
  display: inline-block;
  position: relative;
  background-color: transparent;
  cursor: pointer;
  border: 0;
  padding: 0;
  color: #00f;
  text-decoration: underline;
  font: inherit;
}
<p>A button that looks like a <button type="button" class="link">link</button>.</p>

这样你就可以指定你的onclick事件。我建议通过脚本绑定,而不是在元素标签上使用onclick属性。唯一需要注意的是旧版本IE中的伪3D文本效果无法禁用。


如果您必须使用A元素,请使用javascript:void(0);,原因如上所述。

  • 始终会拦截点击事件,以防您的onclick事件失败。
  • 不会发生错误加载调用或基于散列更改触发其他事件的情况。
  • 哈希标记可能会导致意外行为(如果单击失败,则onclick抛出),除非它是合适的落下行为,并且您想要更改导航历史记录,否则应避免使用它。

注意:您可以将0替换为字符串,例如javascript:void('Delete record 123'),该字符串可作为额外指示器,显示单击实际执行的操作。


54
这个答案应该在顶部。如果你正在面临这个困境,很可能你实际上需要一个“按钮”。幸运的是,IE9的市场份额正在迅速下降,而1像素的活动效果不应阻止我们使用语义化标记。<a>是一个链接,它的作用是将你带到某个地方,对于操作,我们有<button> - mjsarfatti
如果onclick中的操作将作为链接(导航到其他页面或在新窗口中打开某些内容),那么它应该语义上是一个<a>标签。如果操作是页面内弹出窗口或同一页上的其他功能,则应该是一个<button> - undefined

152

最好第一个链接附带一个真实的网址,以防用户禁用JavaScript。确保返回false以防止JavaScript执行时触发点击事件。

<a href="#" onclick="myJsFunc(); return false;">Link</a>

如果您使用Angular2,则可以使用以下方式:

<a [routerLink]="" (click)="passTheSalt()">Click me</a>

请参见此处:https://dev59.com/RFsV5IYBdhLWcg3w6iZ8#45465728


20
在启用JavaScript并支持该函数的用户代理中,运行JavaScript函数,如果JavaScript在某种原因下失败,则回退到页面顶部的链接?这通常不是一个明智的备选方案。 - Quentin
26
最好能够提供实际链接,以防用户禁用JavaScript。即使只是解释网站需要JS才能正常运行,也应该跳转到一个有用的页面而不是#。如果出现问题,我希望开发人员在部署前使用适当的浏览器功能检测等。 - Zach

111

如果你问我的话,如果你的“链接”只是为了运行一些JavaScript代码,那么它就不符合链接的定义,而是一段文本配上一个JavaScript函数。我建议使用一个带有onclick handler标签,再加上一些基本的CSS来模拟一个链接。链接是用于导航的,如果你的JavaScript代码不是用于导航,那么它就不应该使用标签。

示例:

function callFunction() { console.log("function called"); }
.jsAction {
    cursor: pointer;
    color: #00f;
    text-decoration: underline;
}
<p>I want to call a JavaScript function <span class="jsAction" onclick="callFunction();">here</span>.</p>


137
这种方法限制了“链接”只能通过鼠标操作。通过键盘可以访问锚点,并且当按下回车键时触发其“onclick”事件。 - AnthonyWJones
45
在CSS中硬编码颜色会阻止浏览器使用用户可能定义的自定义颜色,这可能会影响可访问性。 - Hosam Aly
38
<span> 标签并不用于执行任何操作,而是用 <a> 锚点和 <button> 按钮来实现这一点! - redShadow
30
在这里使用"按钮(buttons)"是更好的选择,而使用"跨度(span)"则不是。 - apnerve
“链接是用于导航的,如果您的JavaScript代码不是用于导航,则不应该使用<a>标签。”即使JavaScript代码是“用于导航”,但并不是每次都适合使用链接。 - Sebastian Simon

107

理想情况下,您应该这样做:

<a href="javascriptlessDestination.html" onclick="myJSFunc(); return false;">Link text</a>
或者,更好的方法是在HTML中将默认操作链接放置到元素中,然后通过JavaScript在DOM渲染后以非侵入式的方式向元素添加onclick事件,从而确保如果JavaScript不存在或未被使用,您不会将无用的事件处理程序散布在代码中并潜在地使您的实际内容变得模糊(或至少分散注意力)。

78

仅使用#可能导致一些有趣的动作,因此建议使用#self以节省输入JavaScript代码的努力。


36
作为参考,#self 似乎并不特殊。在文档中,任何不匹配任何元素的名称或ID(且不为空或为“top”)的片段标识符应该具有相同的效果。 - cHao
与cHao所说的一样,您只需要在单击(onclick)元素a时返回false即可产生相同的效果。 - syahid246

72

我使用以下代码

<a href="javascript:;" onclick="myJsFunc();">Link</a>

相反地

<a href="javascript:void(0);" onclick="myJsFunc();">Link</a>

href="javascript:"href="javascript:void 0;"是等价的,但它们同样糟糕。 - Sebastian Simon
这个答案没有任何理据。光说不练也没有帮助。 - isherwood

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