如何防止默认锚标签?

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

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

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

283769 次浏览

你可以将$event对象传递给你的方法,并在它上调用$event.preventDefault(),这样默认的处理就不会发生:

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


// then in your controller.do($event) method
$event.preventDefault()

根据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 />

我更喜欢使用指令来处理这类事情。这里有一个例子

<a href="#" ng-click="do()" eat-click>Click Me</a>

eat-click的指令代码:

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

现在你可以将eat-click属性添加到任何元素,它将自动获得__abc1。

好处:

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

我找到的最简单的解决方法是:

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

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

<a href="javascript:void(0)" ....>

另一种可能是:

<span ng-click="do()">Click</span>

更新:我已经改变了我对这个解决方案的想法。经过更多的开发和时间的努力,我相信更好的解决这个问题的方法是:

<a ng-click="myFunction()">Click Here</a>

然后更新你的css来增加一个额外的规则:

a[ng-click]{
cursor: pointer;
}

它更简单,提供完全相同的功能,效率更高。希望这对将来寻找这个解决方案的人有所帮助。


以下是我之前的解决方案,我把它放在这里只是为了遗留的目的:

如果你经常遇到这个问题,一个简单的指令可以解决这个问题:

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();
});
}
}
};
});

它检查所有锚标记(<a></a>),看看它们的href属性是否为空字符串("")或散列('#'),或者存在ng-click赋值。如果发现其中任何一种情况,它将捕获事件并防止默认行为。

唯一的缺点是它为所有锚标记运行这个指令。因此,如果页面上有很多锚标记,而你只想阻止其中一小部分的默认行为,那么这个指令就不是很有效。然而,我几乎总是想preventDefault,所以我在我的AngularJS应用程序中使用这个指令。

我需要存在href属性的值退化(当js被关闭),所以我不能使用空href属性(或“#”),但上面的代码没有为我工作,因为我需要一个事件(e)变量。我创建了自己的指令:

angular.module('MyApp').directive('clickPrevent', function() {
return function(scope, element, attrs) {
return element.on('click', function(e) {
return e.preventDefault();
});
};
});

在HTML中:

<a data-click-prevent="true" href="/users/sign_up" ng-click="openSignUpModal()">Sign up</a>

既然你在制作网页应用,为什么还需要链接呢?

把锚换成按钮!

<button ng-click="do()"></button>

借用tennisgent的答案。我喜欢你不需要创建一个自定义指令来添加所有的链接。然而,我不能让他在IE8中工作。下面是最终对我有用的方法(使用angular 1.0.6)。

注意,'bind'允许你使用angular提供的jqLite,所以不需要用完整的jQuery来包装。还需要stoppropagation方法。

.directive('a', [
function() {
return {
restrict: 'E',
link: function(scope, elem, attrs) {


elem.bind('click', function(e){
if (attrs.ngClick || attrs.href === '' || attrs.href == '#'){
e.preventDefault();
e.stopPropagation();
}
})
}
};
}
])
ng-click="$event.preventDefault()"

您可以执行以下操作

1.从锚(a)标记中删除href属性

2.将css中的指针指针设置为ng click元素

 [ng-click],
[data-ng-click],
[x-ng-click] {
cursor: pointer;
}

我认为:

<a ng-click="do()">Click</a>
  • 因为根据文档,你应该可以离开href,然后Angular会为你处理防止的默认值!

整个这个防止默认的事情一直困扰着我,所以我已经创建了一个JSFiddle 说明了Angular何时何地阻止默认值.

.

JSFiddle使用的是Angular的a指令——所以应该是完全一样的。你可以在这里看到源代码:一个标签源代码

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

我本想把这个文档发布到ngHref上,但因为我的名声,我不能。

如果仍然相关:

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


...


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


...

所以阅读这些答案,@Chris仍然有最“正确”的答案,我想,但它有一个问题,它没有显示“指针”....

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

  1. 使用javascript:void(0)代替#:

    <a href="javascript:void(0)" ng-click="doSomething()">Do Something</a>
    
  2. Use $event.preventDefault() in the ng-click directive (so you don't junk up your controller with DOM-related references):

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

Personally I prefer the former over the latter. javascript:void(0) has other benefits that are discussed here. There is also discussion of "unobtrusive JavaScript" in that link which is frighteningly recent, and doesn't necessarily directly apply to an angular application.

尽管雷诺给出了一个很好的解决方案

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

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

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

就是我的解

或者如果你需要内联,那么你可以这样做:

<a href="#" ng-click="show = !show; $event.preventDefault()">Click to show</a>

我在使用锚进行角引导下拉时遇到了同样的问题。我发现唯一的解决方案,避免不必要的副作用(即。因为使用preventDefault())而没有关闭的下拉列表使用以下方法:

 <a href="javascript:;" ng-click="do()">Click</a>

我一直都是这么做的。效果好极了!

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

超文本标记语言

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

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

JS

$scope.do = function() {
alert("do here anything..");
}

(或)

你可以这样做,这已经有人讨论过了。

超文本标记语言

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

JS

$scope.do = function(event) {
event.preventDefault();
event.stopPropagation()
}
/* NG CLICK PREVENT DEFAULT */


app.directive('ngClick', function () {
return {
link: function (scope, element, attributes) {
element.click(function (event) {
event.preventDefault();
event.stopPropagation();
});
}
};
});

试试这个选项,我可以看到上面还没有列出:

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

如果你从来不想去href…您应该更改标记,使用按钮而不是锚标记,因为从语义上讲,它既不是锚也不是链接。相反,如果你有一个按钮,做一些检查,然后重定向,它应该是一个链接/锚标签,而不是一个按钮…用于SEO目的以及测试[此处插入测试套件]。

对于你只想有条件地重定向的链接,比如提示保存更改,或确认脏状态…你应该使用ng-click="someFunction($event)"和在someFunction上你的validationError preventDefault和或stopPropagation。

你能做并不意味着你应该做。Javascript:void(0)工作得很好…但是由于邪恶的黑客/破解者,浏览器标记应用程序/网站在href中使用javascript…看不出有什么理由在上面低头打字。

从2010年到现在已经是2016年了,没有理由在任何地方使用像按钮一样的链接……如果你仍然要支持IE8及以下版本,你需要重新评估你的公司。

你应该做的是完全省略href属性。

如果你查看a元素指令的源代码(它是Angular核心的一部分),它在第29 - 31行声明:

if (!element.attr(href)) {
event.preventDefault();
}

这意味着Angular已经解决了没有href的链接问题。你仍然有唯一的问题是css问题。你仍然可以将指针样式应用于具有ng-clicks的锚点,例如:

a[ng-click] {
/* Styles for anchors without href but WITH ng-click */
cursor: pointer;
}

因此,你甚至可以通过用一种微妙的、不同的样式来标记真正的链接,从而使你的网站更容易访问。

编码快乐!

很多答案似乎都是多余的。对我来说,这很有效

 <a ng-href="#" ng-click="$event.preventDefault();vm.questionContainer($index)">\{\{question.Verbiage}}</a>
你可以在$location的Html5Mode中禁用url重定向来实现目标。您可以在页面使用的特定控制器中定义它。 就像这样:

app.config(['$locationProvider', function ($locationProvider) {
$locationProvider.html5Mode({
enabled: true,
rewriteLinks: false,
requireBase: false
});
}]);

如果你使用的是Angular 8或更高版本,你可以创建一个指令:

import { Directive, HostListener } from '@angular/core';


@Directive({
selector: '[preventDefault]'
})
export class PreventDefaultDirective {


@HostListener("click", ["$event"])
public onClick(event: any): void
{
console.log('click');
debugger;
event.preventDefault();
}


}

在组件的锚标记上,你可以这样连接它:

  <a ngbDropdownToggle preventDefault class="nav-link dropdown-toggle" href="#" aria-expanded="false" aria-haspopup="true" id="nav-dropdown-2">Pages</a>

App Module应该有它的声明:

import { PreventDefaultDirective } from './shared/directives/preventdefault.directive';




@NgModule({
declarations: [
AppComponent,
PreventDefaultDirective

在我的例子中,Angular: 10 -工作

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

更新:此方法将重新加载解析器。由于@Meeker