如何防止锚标签的默认?

Mic*_*ael 341 preventdefault angularjs

假设我有一个锚标记,例如

<a href="#" ng-click="do()">Click</a>
Run Code Online (Sandbox Code Playgroud)

如何防止浏览器导航到AngularJS中的#?

Chr*_*ris 319

根据ngHref文档,你应该能够离开href或做href ="".

<input ng-model="value" /><br />
<a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
<a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
<a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
<a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />
Run Code Online (Sandbox Code Playgroud)

  • 请记住,这也使标签不可标记,这不是非常易于访问. (34认同)
  • 不使用href属性的唯一缺点是当鼠标悬停在链接上时会丢失正常的"指针"光标.您可以通过向样式表添加规则来解决此问题:a:hover {cursor:pointer; } (25认同)
  • 这是唯一真正的好答案.任何需要触摸DOM或本机事件的东西都值得怀疑 (6认同)
  • 这是正确的答案.如果从<a>属性中删除href,AngularJS将调用prevent default: (4认同)
  • 对我来说,浏览器仍然会点击点击动作:/ (3认同)

ten*_*ent 258

更新:我已经改变了对这个解决方案的看法.经过更多的开发和花在这方面的时间,我相信这个问题的更好的解决方案是执行以下操作:

<a ng-click="myFunction()">Click Here</a>
Run Code Online (Sandbox Code Playgroud)

然后更新您css的额外规则:

a[ng-click]{
    cursor: pointer;
}
Run Code Online (Sandbox Code Playgroud)

它更简单,提供完全相同的功能,效率更高.希望将来可能有助于其他人查找此解决方案.


以下是我以前的解决方案,我将其留在这里仅用于遗留目的:

如果您遇到这个问题很多,那么解决此问题的简单指令如下:

app.directive('a', function() {
    return {
        restrict: 'E',
        link: function(scope, elem, attrs) {
            if(attrs.ngClick || attrs.href === '' || attrs.href === '#'){
                elem.on('click', function(e){
                    e.preventDefault();
                });
            }
        }
   };
});
Run Code Online (Sandbox Code Playgroud)

它检查所有锚标记(<a></a>)以查看它们的href属性是空字符串("")还是哈希('#')或者是否有ng-click赋值.如果它发现任何这些条件,它会捕获事件并阻止默认行为.

唯一的缺点是它为所有锚标签运行此指令.因此,如果页面上有很多锚标记,并且您只想阻止少数锚标记的默认行为,则该指令效率不高.但是,我几乎总是想要preventDefault,所以我在AngularJS应用程序中使用了这个指令.

  • 如果您不关心您网站上的**辅助功能**,这很好.通过不使用href,就无法使用键盘来标记该项目.除非您添加了tabindex.考虑到所有这些,为什么不使用preventDefault ...?这就是它的用途. (6认同)
  • 谢谢@matejkramny,非常有建设性的批评.有什么建议让它不那么"凌乱"吗? (2认同)
  • 这种方法很有效,但是对于一个非常简单的问题来说,它真的有点过分.Angular允许您使用$ event访问事件对象,因此您可以完全按照在js或jquery点击事件中执行的操作.请参阅此答案http://stackoverflow.com/a/19240232/1826354以及我对它的评论 (2认同)

mna*_*mna 235

您可以将$ event对象传递给您的方法,并对其进行调用$event.preventDefault(),以便不会发生默认处理:

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

// then in your controller.do($event) method
$event.preventDefault()
Run Code Online (Sandbox Code Playgroud)

  • 是的,你也可以调用$ event.stopPropagation(),这样事件就不会起泡(基本上,你可以访问W3C定义的Event对象:http://www.w3.org/TR/ DOM-Level-2-Events/events.html#Events-Event) (13认同)
  • 将$事件传递给控制器​​意味着在控制器中引用DOM,这意味着您已将视图和控制器耦合在一起.你可以直接在你的计算表​​达式中调用$ event方法:`ng-click ="do(); $ event.preventDefault()`例如......但是,没有必要因为@Chris的答案是正确的.可能会帮助人们在他们嵌套ngClicks并且他们想要调用`$ event.stopPropagation()`的情况下. (4认同)
  • 最后是SEO友好的解决方案.您可能还想在不重新加载ng-view的情况下更新浏览器URL - http://joelsaupe.com/programming/angularjs-change-path-without-reloading/这样您就可以链接不重新加载视图,但可以打开在新标签页和搜索引擎中可以关注它们.好极了! (2认同)

djs*_*ith 110

我更喜欢使用指令来做这种事情.这是一个例子

<a href="#" ng-click="do()" eat-click>Click Me</a>
Run Code Online (Sandbox Code Playgroud)

以及指令代码eat-click:

module.directive('eatClick', function() {
    return function(scope, element, attrs) {
        $(element).click(function(event) {
            event.preventDefault();
        });
    }
})
Run Code Online (Sandbox Code Playgroud)

现在,您可以将该eat-click属性添加到任何元素,它将preventDefault()自动生成.

优点:

  1. 您不必将丑陋的$event对象传递给您的do()函数.
  2. 您的控制器更易于单元测试,因为它不需要存根$event对象

  • 我试过`angular.element(element).bind('click',function(event){...});`.有效.参考:[jQLite](http://docs.angularjs.org/api/angular.element) (6认同)
  • **额外的好处** - 这也适用于**IE8**及以下,如果这对你很重要. (3认同)
  • 如果你问我,为简单的事情引入一个指令看起来有点臃肿......请在下面查看Chris的回答 (2认同)

zai*_*eer 52

虽然雷诺给出了很好的解决方案

<a href="#" ng-click="do(); $event.preventDefault()">Click</a> 
Run Code Online (Sandbox Code Playgroud)

我个人发现在某些情况下你还需要$ event.stopPropagation()以避免一些副作用

<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();">
    Click</a>
Run Code Online (Sandbox Code Playgroud)

将是我的解决方案


Clé*_*aud 33

我找到的最简单的解决方案就是这个:

<a href="#" ng-click="do(); $event.preventDefault()">Click</a>
Run Code Online (Sandbox Code Playgroud)


The*_* Oz 33

ng-click="$event.preventDefault()"
Run Code Online (Sandbox Code Playgroud)

  • 这是最好的解决方案.当然,您也可以将$ event对象传递给scope函数.像ng-click ="myFunction($ event,otherParams),然后是myFunction中的$ event.preventDefault().滚动你自己的指令就是矫枉过正 (12认同)

Ben*_*esh 10

因此,通过这些答案,@ Chris仍然有最"正确"的答案,我想,但它有一个问题,它没有显示"指针"....

所以这里有两种方法可以解决这个问题,而无需添加游标:指针样式:

  1. 使用javascript:void(0)而不是#:

    <a href="javascript:void(0)" ng-click="doSomething()">Do Something</a>
    
    Run Code Online (Sandbox Code Playgroud)
  2. $event.preventDefault()ng-click指令中使用(所以你不要使用与DOM相关的引用来破坏你的控制器):

    <a href="#dontGoHere" ng-click="doSomething(); $event.preventDefault()">Do Something</a>
    
    Run Code Online (Sandbox Code Playgroud)

就个人而言,我更喜欢前者而不是后者.这里讨论的javascript:void(0)其他好处.在该链接中还讨论了"不显眼的JavaScript",这是最近可怕的,并不一定直接适用于角度应用.

  • 为什么这是downvoted?我还注意到,克里斯的回答中没有显示指针。 (2认同)
  • javascript:void(0) 比 # 好得多,如果您配置错误,它可以对路由起作用。+1 (2认同)
  • 我刚想写一个答案。你也可以做`javascript:;` (2认同)

Fiz*_*han 9

你可以这样做

1. href从anchor(a)标签中删除属性

2.将css中的指针光标设置为ng单击元素

 [ng-click],
 [data-ng-click],
 [x-ng-click] {
     cursor: pointer;
 }
Run Code Online (Sandbox Code Playgroud)


val*_*mar 8

HTML

这里是纯angularjs:接近ng-click函数你可以通过分隔分号来编写preventDefault()函数

<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();">Click me</a>
Run Code Online (Sandbox Code Playgroud)

JS

$scope.do = function() {
    alert("do here anything..");
}
Run Code Online (Sandbox Code Playgroud)

(要么)

你可以这样做,这里已经讨论了一些.

HTML

<a href="#" ng-click="do()">Click me</a>
Run Code Online (Sandbox Code Playgroud)

JS

$scope.do = function(event) {
    event.preventDefault();
    event.stopPropagation()
}
Run Code Online (Sandbox Code Playgroud)


pol*_*1er 6

尝试这个我可以看到的选项尚未列在上面:

<a href="" ng-click="do()">Click</a>
Run Code Online (Sandbox Code Playgroud)


小智 5

避免href事件的最安全方法是将其定义为

<a href="javascript:void(0)" ....>
Run Code Online (Sandbox Code Playgroud)


sid*_*son 5

由于您正在制作网络应用程序,为什么需要链接?

将锚点交换到按钮!

<button ng-click="do()"></button>
Run Code Online (Sandbox Code Playgroud)

  • 既然 wen 不能有锚点? (2认同)
  • @sidonaldson实际上,现在很多网络应用程序在很大程度上依赖于链接.看看angularjs路由. (2认同)
  • 这个答案应该有更多的赞成票。在许多情况下,如果您想阻止默认锚点行为,您可以将锚点用作按钮而不是链接。 (2认同)

mar*_*ose 5

我会去:

<a ng-click="do()">Click</a>
Run Code Online (Sandbox Code Playgroud)
  • 因为根据文档,您应该可以离开 href,然后 Angular 将为您处理阻止默认值!

整个这个防止默认的事情让感到困惑,所以我创建了一个JSFiddle 来 说明 Angular 何时何地阻止 default

JSFiddle 正在使用 Angular 的 a 指令 - 所以它应该完全相同。你可以在这里看到源代码:一个标签源代码

我希望这将有助于澄清一些。

我本来希望将文档发布到 ngHref,但由于我的声誉我不能。


小智 5

如果仍然相关:

<a ng-click="unselect($event)" />

...

scope.unselect = function( event ) {
 event.preventDefault();
 event.stopPropagation();
}

...
Run Code Online (Sandbox Code Playgroud)


Cat*_*ish 5

这是我一直在做的。奇迹般有效!

<a href ng-click="do()">Click</a>
Run Code Online (Sandbox Code Playgroud)