取消嵌套的 ng-click 调用之间的事件传播的最佳方法是什么?

举个例子。比方说,我想有一个图像覆盖像许多网站。所以当你点击一个缩略图时,整个窗口会出现一个黑色的覆盖层,并且图像的放大版本会以它为中心。单击黑色覆盖将解除它; 单击图像将调用显示下一个图像的函数。

译者:

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
<img src="http://some_src" ng-click="nextImage()"/>
</div>

Javascript:

function OverlayCtrl($scope) {
$scope.hideOverlay = function() {
// Some code to hdie the overlay
}
$scope.nextImage = function() {
// Some code to find and display the next image
}
}

问题是,在这种设置下,如果单击图像,就会调用 nextImage()hideOverlay()。但是我想要的是只调用 nextImage()

我知道你可以像下面这样在 nextImage()函数中捕获和取消事件:

if (window.event) {
window.event.stopPropagation();
}

但是我想知道是否有一种更好的 AngularJS 方法,它不需要我用这个代码片段给覆盖图中的元素添加所有函数的前缀。

159098 次浏览

使用 $event.stopPropagation():

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
<img src="http://some_src" ng-click="nextImage(); $event.stopPropagation()" />
</div>

这里有一个演示: http://plnkr.co/edit/3Pp3NFbGxy30srl8OBmQ?p=preview

@ JosephSilber 所说的,或者将 $event 对象传递到 ng-click回调函数并停止其内部的传播:

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
<img src="http://some_src" ng-click="nextImage($event)"/>
</div>
$scope.nextImage = function($event) {
$event.stopPropagation();
// Some code to find and display the next image
}

如果你不想添加停止传播到所有的链接,这也可以工作。可扩展性更强一些。

$scope.hideOverlay( $event ){


// only hide the overlay if we click on the actual div
if( $event.target.className.indexOf('overlay') )
// hide overlay logic


}

我喜欢使用指令的想法:

.directive('stopEvent', function () {
return {
restrict: 'A',
link: function (scope, element, attr) {
element.bind('click', function (e) {
e.stopPropagation();
});
}
};
});

然后使用如下指令:

<div ng-controller="OverlayCtrl" class="overlay" ng-click="hideOverlay()">
<img src="http://some_src" ng-click="nextImage()" stop-event/>
</div>

如果您愿意,您可以使这个解决方案更加通用,就像这个对另一个问题的回答一样: https://stackoverflow.com/a/14547223/347216

有时候,这样做可能最有意义:

<widget ng-click="myClickHandler(); $event.stopPropagation()"/>

我之所以选择这样做,是因为我不希望 myClickHandler()在许多其他使用它的地方停止事件传播。

当然,我可以为 Handlder 函数添加一个布尔参数,但是 stopPropagation()true更有意义。

如果您在模板的父元素上插入 ng-click = “ $event. stopProgation”,那么当 stop Progation 在树上冒泡时,它将被捕获,因此您只需要为整个模板编写一次。

您可以在 ng-click之上注册另一个指令,修改 ng-click的默认行为并停止事件传播。这样您就不必手动添加 $event.stopPropagation

app.directive('ngClick', function() {
return {
restrict: 'A',
compile: function($element, attr) {
return function(scope, element, attr) {
element.on('click', function(event) {
event.stopPropagation();
});
};
}
}
});

这对我有用:

<a href="" ng-click="doSomething($event)">Action</a>


this.doSomething = function($event) {
$event.stopPropagation();
$event.preventDefault();
};
<div ng-click="methodName(event)"></div>

IN 控制器的使用

$scope.methodName = function(event) {
event.stopPropagation();
}

在我的情况下,event.stopPropagation();是使我的网页刷新每次我按下一个链接,所以我必须找到另一个解决方案。

所以我所做的就是捕捉父级上的事件,并使用 event.target阻塞触发器,如果事件实际上来自于他的孩子。

解决办法如下:

if (!angular.element($event.target).hasClass('some-unique-class-from-your-child')) ...

因此,基本上只有当您单击父组件时,从父组件进行的 ng-click 才能起作用。如果你点击这个孩子,它不会通过这个条件,它不会继续它的流程。