在Angular.js中,href覆盖了ng-click。

123

当定义了href和ng-click属性时:

<a href="#" ng-click="logout()">Sign out</a>

href属性优先于ng-click。

我正在寻找提高ng-click优先级的方法。

href是Twitter Bootstrap所必需的,我不能删除它。


你能详细说明一下“Twitter Bootstrap需要href”吗?它的哪个部分需要?CSS还是JavaScript? - pkozlowski.opensource
Twitter Bootstrap的导航“小部件”设置为使用链接,如果您添加一个按钮到其中,即使是样式看起来像链接的按钮,它也会破坏导航的样式。这可能不是语义化的HTML,但@sketchfemme的解决方案可以实现我(以及可能是Paul)想要的效果。 - BenCr
忽略我之前说的,如果您使用正确的HTML和类,导航条与按钮完美配合。http://getbootstrap.com/components/#navbar - BenCr
你应该接受 Mithu 的答案,即使用空的URL。 - Peter Morris
1
@Paul 原帖提问如何使<a href>链接不进行导航。被采纳的答案是转换为按钮。虽然这样做可以解决问题,但对于像我这样被迫使用 <a href> 的人来说,尤其是因为它是bootstrap菜单或其他什么东西。针对这个特定问题的正确解决方案是使用空url的 <a href="" ng-click="whatever()">Log out</a> - 我测试过并确认它有效。幸运的是,有人提供了正确的答案,否则我还会卡在那里。 - Peter Morris
17个回答

246

4
当我尝试这样做时,所有的链接似乎都变成了已访问过的状态,这不是我想要的行为。另一种方式(href="#")会导致页面重新加载,也是错误的。 - Rhys van der Waerden
4
这会导致IE9不显示手型光标。使用href=""可以解决这个问题。 - Juampy NR
1
@juampy,链接的交接可以通过CSS处理。这个答案是官方的AngularJS处理方式。 - thenetimp
#符号将被视为哈希链接。 - sheriffderek
3
<a href="javscript:void(0)" ng-click="logout()">登出</a>也会对您有所帮助。 - Marios Fakiolas

90

你可以直接在模板中简单地阻止点击事件的默认行为。

<a href="#" ng-click="$event.preventDefault();logout()" />
根据Angular文档,像ngClick和ngFocus这样的指令在表达式作用域内公开了一个$event对象。

12
这是个很好的解决方案。如果你有一个href链接,在右键点击它时可以在新标签页中打开,但左键点击时它会调用ng-click。正是我一直在寻找的。 - Tom Grant
再次给出了一个优秀的答案。左键和右键都可以工作。 - Jay Jay Jay
非常好用,可以让Bootstrap轮播控件在不触发路由的情况下正常工作。谢谢! - Jason Maggard
太好了!我可以继续使用链接,在谷歌上获得更多的索引,并使用ng-click调用Ajax。谢谢。 - GIA
很棒的解决方案,快速且实用。谢谢! - Josue Rocha
你救了我一命,非常感谢你。 - Naila Akbar

74

这里是另一种解决方案:

<a href="" ng-click="logout()">Sign out</a>

即从href属性中删除#符号。


1
对于所提出的问题,这应该是解决方案。同时也适用于Angular 1.1.5。 - Sindre
20
似乎在Android 2.3.x浏览器中,<a href="" ng-click="">将阻止ng-click的触发。最终我使用了<a href="javascript:void(0)" ng-click="">。 - duckegg
2
鸭蛋的建议是最好的一个 - Jiří Vypědřík

36

如果您不需要uri,建议使用button标签。


是的,如果您能详细说明Twitter Bootstrap需要什么,也许我可以提供更多帮助。 - Geoff
这个在搜索引擎中如何工作?我正在使用AngularJS路由,并需要在服务中维护状态,因此对于所有内部应用程序链接,我使用$location,但删除href会使搜索引擎无法跟随网站。 - Darrrrrren
2
按钮内部不能包含其他元素,因此在进行样式设计时,如果需要在其中放置其他元素,则不建议这样做。 - sheriffderek

28

再给你一个提示。如果你需要真实的URL(以支持浏览器可访问性),你可以按以下方式操作:

模板:

<a ng-href="{{link}}" ng-click="$event.preventDefault(); linkClicked(link)">{{link}}</a>

指令:

$scope.linkClicked = function(link){
    // your code here
    $location.path(link);
};

以这种方式,您在linkClicked()中的代码将有机会在导航到链接之前执行


这个解决方案可行,只改变了左键点击的行为,右键点击保持不变(上下文菜单),包括在href中添加链接的可能性。因此,与TooMuchTenacious相比,这是一个更通用的解决方案,后者实际上更直接地回答了问题。 - Exocom

22
在Angular中,<a>是指令。因此,如果您的href为空或没有href,Angular将调用event.preventDefault
源代码来看:
    element.on('click', function(event){
      // if we have no href url, then don't navigate anywhere.
      if (!element.attr(href)) {
        event.preventDefault();
      }
    });

这是一个展示缺少 href 的情况的 plnkr

14

这对我在IE 9和AngularJS v1.0.7中有效:

<a href="javascript:void(0)" ng-click="logout()">Logout</a>

感谢duckeggs的评论提供了可行的解决方案!


有效,该链接不会改变您的URL并且不会被标记为已访问。最佳答案! - Jim109

13

这个问题有很多答案,但似乎对于实际发生的事情存在一些混淆。

首先,你的前提条件

"href在Angular.js中会覆盖ng-click"

是错误的。实际发生的是,在您单击之后,该单击事件首先由angular处理(由angular 1.x中的ng-click指令和angular 2.x+中的click定义),然后继续传播(最终触发浏览器导航到使用href属性定义的url)。(有关javascript中事件传播的更多信息,请参见此处)

如果您想避免这种情况,则应使用事件接口的preventDefault()方法取消事件传播:

<a href="#" ng-click="$event.preventDefault();logout()" />

(这是纯JavaScript功能,与Angular无关)

现在,这已经可以解决你的问题了,但这不是最佳解决方案。Angular正确地推广MVC模式。使用此解决方案,您的HTML模板与JavaScript逻辑混合在一起。您应该尽可能避免这种情况,并将逻辑放入Angular控制器中。所以更好的方式是:

<a href="#" ng-click="logout($event)" />

而在你的logout()方法中:

logout($event) {
   $event.preventDefault();
   ...
}

现在,单击事件将不会传递到浏览器,因此它不会尝试加载由 href 指向的链接。(但请注意,如果用户右键单击链接并直接打开链接,则根本不会有单击事件。相反,它将直接加载由href属性指向的URL。)

关于浏览器中已访问链接颜色的注释。同样,这与 Angular 无关。如果您的href="..." 默认指向浏览器中的已访问 URL,则链接颜色将是不同的。这是由CSS :visited Selector 控制的,您可以修改您的 CSS 来覆盖这种行为:

a {
   color:pink;
}

提示1:

有些答案建议使用:

<a href .../>

href 是一个 Angular 指令。当您的模板被 Angular 处理时,它会被转换为:

href 是一种 Angular 指令。当 Angular 处理模板时,它将被转换为:

<a href="" .../>

这两种方法本质上是相同的。


5
只需在 href 前面写上 ng-click 即可。这对我有用。

<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@1.5.0" data-semver="1.5.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
    <script>
    angular.module("module",[])
.controller("controller",function($scope){
  
  $scope.func =function(){
    console.log("d");
  }
  
})</script>
  </head>

  <body ng-app="module" ng-controller="controller">
    <h1>Hello ..</h1>
    <a ng-click="func()" href="someplace.html">Take me there</a>
  </body>

</html>


2

我认为您不需要从href中删除“#”。以下内容适用于Angularjs 1.2.10。

<a href="#/" ng-click="logout()">Logout</a>

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