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

时间:2013-03-04 02:15:12

标签: angularjs

这是一个例子。假设我希望像许多网站一样覆盖图像。因此,当您单击缩略图时,整个窗口上会出现黑色叠加层,并且图像的较大版本将居中。点击黑色叠加层即可解散它;单击图像将调用显示下一个图像的功能。

html:

<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方法,不需要我使用这个片段为叠加层内的元素添加前缀。

10 个答案:

答案 0 :(得分:184)

@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
}

答案 1 :(得分:169)

使用$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

答案 2 :(得分:100)

我喜欢使用指令的想法:

.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

答案 3 :(得分:29)

有时,这样做最有意义:

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

我选择这样做是因为我不希望myClickHandler()在其他许多地方停止事件传播。

当然,我可以在处理函数中添加一个布尔参数,但stopPropagation()true更有意义。

答案 4 :(得分:7)

这对我有用:

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

this.doSomething = function($event) {
  $event.stopPropagation();
  $event.preventDefault();
};

答案 5 :(得分:4)

如果您不想将停止传播添加到所有链接,这也可以。更具可扩展性。

$scope.hideOverlay( $event ){

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

}

答案 6 :(得分:0)

如果你插入ng-click =&#34; $ event.stopPropagation&#34;在模板的父元素上,stopPropogation将在树上冒泡时被捕获,因此您只需为整个模板编写一次。

答案 7 :(得分:0)

您可以在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();
                });
            };
        }
    }
});

答案 8 :(得分:0)

<div ng-click="methodName(event)"></div>

IN控制器使用

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

答案 9 :(得分:0)

对于我来说,event.stopPropagation();每次按下链接时都会刷新页面,所以我不得不寻找其他解决方案。

所以我要做的是在父项上捕获该事件并阻止触发,如果该触发实际上来自他的孩子,则使用event.target

这是解决方案:

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

因此,基本上,只有当您单击父级时,您才能从父级组件进行ng-click。如果您单击该孩子,则它不会通过此条件,也不会继续进行下去。