<a href="#" ng-click="do()">Click</a>
如何防止浏览器导航到AngularJS中的#?
#1 楼
更新:此后,我改变了主意。经过更多的开发并花了很多时间在解决这个问题上,我相信对这个问题的更好解决方案是执行以下操作:<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应用程序中都使用了此指令。评论
感谢@matejkramny,非常有建设性的批评。有什么建议可以减少它的“混乱”?
–网球
13-10-16在13:31
如其他答案所述,具有空白的href属性在不同的浏览器中具有不同的行为。尽管我同意这是迄今为止最干净,最有效的解决方案,但确实存在一些跨浏览器的问题。使用指令方法可以使浏览器照常处理标记,但仍可以向OP获取他们正在寻找的答案。
–网球
13年11月26日在4:19
这很奏效,但对于一个非常简单的问题,它的严重矫over过正。 Angular使您可以使用$ event访问事件对象,因此您可以完全执行纯js或jquery click事件中的操作。看到这个答案stackoverflow.com/a/19240232/1826354和我对此的评论
–查理·马丁(Charlie Martin)
14年2月13日在19:14
是的您可以。这篇文章还有另外两个答案已经按照您的描述进行了。我同意,这太过分了。这就是为什么我做了我所做的更新。
–网球
14年2月14日在21:09
如果您不关心网站的可访问性,那就很好。取消设置href,就无法使用键盘在该项目上切换。除非添加了tabindex。考虑到所有这些,为什么不只使用preventDefault ...?那就是它的目的。
– duhseekoh
2015年2月3日在22:01
#2 楼
根据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 />
评论
这是唯一的实际好答案。任何需要接触DOM或本地事件的问题都是可疑的
– Vincent
13年4月5日在20:21
这是正确的答案。如果从属性中删除href,AngularJS将调用prevent默认值:
–pkozlowski.opensource
13年4月21日在10:41
放弃href属性的唯一缺点是,将鼠标悬停在链接上时会丢失普通的“指针”光标。您可以通过在样式表中添加规则来解决此问题:a:hover {cursor:pointer; }
–卡格尔德
2013年6月9日14:57
请记住,这也会使标签不可贴标签,这对访问性不是很友好。
–Richard Szalay
13年13月13日下午5:33
对我来说,浏览器仍然冒着点击动作:/
–马泰
2015年2月26日,下午3:17
#3 楼
您可以将$ event对象传递给您的方法,然后对其调用$event.preventDefault()
,这样就不会发生默认处理:<a href="#" ng-click="do($event)">Click</a>
// then in your controller.do($event) method
$event.preventDefault()
评论
是的,您还可以调用$ event.stopPropagation()以使事件不会冒泡(基本上,您可以访问W3C定义的Event对象:w3.org/TR/DOM-Level-2- Events / events.html#Events-Event)
–mna
2012年7月31日,1:12
请注意,在撰写本文时,在IE8 / 9和Opera上将href留空(或不存在)是不可行的。这是一年前的事,但我还没有机会再试一次(当时我在Github上打开了一个问题,但我认为他们是在一段时间前重新设置了问题)。如果这是固定的(或者您不关心这些浏览器),则请务必使用Chris的答案!如果有人可以尝试并评论/编辑答案,那就更好了。
–mna
2013年6月6日14:19
@PuerkitoBio-我可以确认IE8及以下版本仍需要$ event.preventDefault()... IE税。
– Scotty.NET
13年7月18日在15:47
将$ event传递给控制器意味着在控制器中引用DOM,这意味着您已经将视图和控制器耦合在一起。您可以在评估的表达式中直接调用$ event方法:例如ng-click =“ do(); $ event.preventDefault()...尽管,但这不是必需的,因为@Chris的答案是正确的。处于嵌套ngClicks且希望调用$ event.stopPropagation()的人。
– Ben Lesh
13年10月8日在21:13
最后是SEO友好的解决方案。您可能还想在不重新加载ng-view的情况下更新浏览器URL-joelsaupe.com/programming/…这样,您的链接不会重新加载视图,但可以在新标签页中打开,搜索引擎可以关注它们。好极了!
–汤姆
2014年7月19日在12:49
#4 楼
我更喜欢对此类事情使用指令。这是一个示例<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
属性赋予任何元素,它将自动进行preventDefault()
的编辑。好处:
您不必将难看的
$event
对象传递到您的do()
函数中。您的控制器更易于单元测试,因为它不需要存入
$event
对象评论
@Kato Angular带有自己的jQuery子集,使我们的生活变得轻松。
–尼尔
13年7月9日在11:04
额外的好处-如果您认为这很重要,那么它也适用于IE8及以下版本。
– Scotty.NET
13年7月19日在10:46
我收到错误:未定义$。我想念什么?
– Bilal Mirza
13年7月24日在9:34
我尝试了angular.element(element).bind('click',function(event){...});。有效。参考:jQLite
– Bilal Mirza
13年7月24日在9:52
如果您问我类似这样的简单指令,似乎有点肿...请在下面查看克里斯的回答
–狂野
13年8月19日在8:42
#5 楼
尽管Renaud提供了很好的解决方案<a href="#" ng-click="do(); $event.preventDefault()">Click</a>
我个人发现在某些情况下,您还需要$ event.stopPropagation()以避免某些副作用
<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();">
Click</a>
将是我的解决方案
#6 楼
我发现的最简单的解决方案是: <a href="#" ng-click="do(); $event.preventDefault()">Click</a>
评论
这不仅最简单,而且不会像其他解决方案中所建议的那样将事件与控制器耦合。应该不惜一切代价避免将事件耦合到控制器,因为这会使测试变得更加困难。
–jornare
14年2月28日在12:18
#7 楼
ng-click="$event.preventDefault()"
评论
这是最好的解决方案。当然,您也可以将$ event对象传递给您的作用域函数。就像ng-click =“ myFunction($ event,otherParams),然后是myFunction中的$ event.preventDefault()一样。
–查理·马丁(Charlie Martin)
14年2月13日在19:07
#8 楼
因此,通读这些答案,我想@Chris仍然是最“正确”的答案,但这有一个问题,它没有显示“指针”...。所以这是无需添加光标即可解决此问题的两种方法:指针样式:
使用
javascript:void(0)
代替#
:<a href="javascript:void(0)" ng-click="doSomething()">Do Something</a>
在
$event.preventDefault()
指令中使用ng-click
(这样就不会用与DOM相关的引用来破坏控制器):<a href="#dontGoHere" ng-click="doSomething(); $event.preventDefault()">Do Something</a>
我个人更喜欢前者。
javascript:void(0)
还有此处讨论的其他好处。在该链接中还讨论了“非侵入式JavaScript”,这是令人恐惧的最新消息,不一定直接应用于有角度的应用程序。评论
为什么这样投票?我还注意到指针未与克里斯的答案一起显示。
– Wim Deblauwe
14年4月14日在7:57
javascript:void(0)比#更好,如果配置不当,它可以对路由起作用。 +1
– Shay Elkayam
2014年4月27日13:32
我正要为此写一个答案。您也可以使用javascript :;
–阿德里安
17年4月9日在3:11
#9 楼
您可以执行以下操作1.从anchor(
href
)标记中删除a
属性2.将css中的指针光标设置为ng click元素
[ng-click],
[data-ng-click],
[x-ng-click] {
cursor: pointer;
}
#10 楼
HTML此处为纯angularjs:在ng-click函数附近,您可以通过分隔分号来编写preventDefault()函数。
<a href="#" ng-click="do(); $event.preventDefault(); $event.stopPropagation();">Click me</a>
JS
$scope.do = function() {
alert("do here anything..");
}
(或)
您可以用这种方式进行操作,这已经在这里讨论过。
HTML
<a href="#" ng-click="do()">Click me</a>
JS
$scope.do = function(event) {
event.preventDefault();
event.stopPropagation()
}
#11 楼
既然要制作Web应用程序,为什么需要链接?将锚点切换到按钮!
<button ng-click="do()"></button>
评论
既然wen不能在webapp中使用锚?
–罗宾·范·巴伦(Robin van Baalen)
14年8月14日在12:48
我指的是大多数Web应用程序都不需要像网站那样的相对链接,它们通常也只使用锚链接作为javascript触发器,而不链接到页面。因此,具有默认样式重置的按钮在语义上同样正确(如果不是更多的话)。
–sidonaldson
14年8月14日在12:50
@sidonaldson实际上,当今很多Web应用程序都严重依赖链接。看一下angularjs路由。
–罗伯特
15年5月22日在9:58
@Robert是的,但是如果您使用内置路由,则无需管理阻止默认设置,它已为您完成。我想因为发布者想取消锚链接,所以他正在谈论非路线链接。例如启动模态等
–sidonaldson
15年5月22日在16:15
这个答案应该有更多的支持。在许多情况下,如果要防止默认的锚定行为,可以将锚定用作按钮而不是链接。
–ItsCosmo
2015年11月17日下午6:06
#12 楼
试试这个我上面还没有看到的选项:<a href="" ng-click="do()">Click</a>
#13 楼
如果仍然相关:<a ng-click="unselect($event)" />
...
scope.unselect = function( event ) {
event.preventDefault();
event.stopPropagation();
}
...
#14 楼
避免在href上发生事件的最安全方法是将其定义为<a href="javascript:void(0)" ....>
#15 楼
我会选择:<a ng-click="do()">Click</a>
,因为根据文档,您应该可以离开href,然后Angular将为您处理prevent default !
整个防止阻止默认设置一直困扰着我,所以我创建了一个JSFiddle
,并举例说明了Angular在何时何地阻止了默认设置。
JSFiddle使用Angular的指令-因此它应该完全一样。您可以在此处查看源代码:标记源代码
我希望这会有助于一些澄清。
我希望将文档发布到ngHref,但我可以不是因为我的声誉。
#16 楼
这就是我一直在做的。<a href ng-click="do()">Click</a>
#17 楼
或者,如果您需要内联,则可以执行以下操作:<a href="#" ng-click="show = !show; $event.preventDefault()">Click to show</a>
#18 楼
很多答案似乎是过分的。对于我来说,这有效 <a ng-href="#" ng-click="$event.preventDefault();vm.questionContainer($index)">{{question.Verbiage}}</a>
#19 楼
我需要存在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>
#20 楼
从网球场的答案中借来的。我喜欢您不必创建自定义指令来添加所有链接。但是,我无法让他在IE8中工作。这是最终对我有用的东西(使用angular 1.0.6)。请注意,“ bind”允许您使用angular提供的jqLite,因此无需使用完整的jQuery进行包装。还需要stopPropogation方法。
.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();
}
})
}
};
}
])
评论
这杀死了很多人。例如,当我使用Twitter Bootstrap的下拉菜单时,我希望传播而不是默认行为。不建议使用此代码段。
–罗宾·范·巴伦(Robin van Baalen)
14年8月14日在12:47
#21 楼
使用锚点进行角度引导时,我遇到了同样的问题。我发现唯一可以避免不必要的副作用(即,由于使用preventDefault()而导致下拉列表无法关闭)的解决方案是使用以下命令: <a href="javascript:;" ng-click="do()">Click</a>
#22 楼
如果您永远不想访问href ...,则应更改标记并使用按钮而不是锚标记,因为从语义上讲它不是锚或链接。相反,如果您有一个进行一些检查然后重定向的按钮,则应该是一个链接/锚标记而不是一个按钮...出于SEO的目的以及测试[在此处插入测试套件]。您只想有条件地重定向的链接,例如提示保存更改或确认脏状态...您应该使用ng-click =“ someFunction($ event)”并在validateError上的someFunction中使用preventDefault和/或stopPropagation。
也仅仅是因为您不能代表您应该这样做。 javascript:void(0)在一天中运作良好...但是由于骇客/骇客浏览器在href内标记了使用javascript的应用/网站,因此没有理由在上面使用ducktype。.
从2010年开始就是2016年,所以您无处不在使用像按钮一样的链接...如果您仍然必须支持IE8及以下版本,则需要重新评估您的营业地点。
#23 楼
/* NG CLICK PREVENT DEFAULT */
app.directive('ngClick', function () {
return {
link: function (scope, element, attributes) {
element.click(function (event) {
event.preventDefault();
event.stopPropagation();
});
}
};
});
#24 楼
您应该做的是完全忽略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;
}
因此,您甚至可以通过使用标记实际链接来使站点更易于访问微妙的,不同的样式然后执行功能的链接。
祝您编程愉快!
#25 楼
您可以在$ location的Html5Mode中禁用url重定向以实现目标。您可以在用于页面的特定控制器中定义它。这样的事情:
app.config(['$locationProvider', function ($locationProvider) {
$locationProvider.html5Mode({
enabled: true,
rewriteLinks: false,
requireBase: false
});
}]);
#26 楼
如果您使用的是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>
应用程序模块应具有其声明:
import { PreventDefaultDirective } from './shared/directives/preventdefault.directive';
@NgModule({
declarations: [
AppComponent,
PreventDefaultDirective
#27 楼
替代方法可能是:<span ng-click="do()">Click</span>
评论
滥用跨度用于点击目的是一种可怕的做法。只需寻求@tennisgent的答案-没有定义href的锚即可。
–罗宾·范·巴伦(Robin van Baalen)
14年8月14日在12:52
@RobinvanBaalen至少从HTML 4.0.1起,将span元素定义为可单击:w3.org/TR/html401/struct/global.html#edef-SPAN w3.org/TR/html5/dom.html#global-attributes html.spec.whatwg.org/multipage/dom.html#global-attributes
–泰伦斯·波多黎各人
2015年1月22日在16:39
如果您点击 Hello span>,是什么时候可以点击?规范可能说的是,可以在诸如或
评论
就像克里斯在下面说的那样,只需忽略href。克里斯(Jesse)并不是这样说的,而是使用href =“来保持鼠标指针的行为。
您只需从href中删除#号即可。
或者只使用href =“ javascript:void(0);”保留指针但不执行任何操作(直到您添加另一个点击处理程序)
您能否将Chris接受的最佳答案和投票最多的答案更改为stackoverflow.com/a/11672909?