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

时间:2021-12-12 22:46:30

Here's an example. Let's say I want to have an image overlay like a lot of sites. So when you click a thumbnail, a black overlay appears over your whole window, and a larger version of the image is centered in it. Clicking the black overlay dismisses it; clicking the image will call a function that shows the next image.

这是一个例子。假设我想要一个像很多网站一样的图像覆盖。所以当你点击一个缩略图时,一个黑色的叠加会出现在你的整个窗口中,一个更大的图像会在窗口中居中。点击黑色覆盖层将其取消;点击图像将调用一个显示下一个图像的函数。

The html:

html:

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

The javascript:

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

The problem is that with this setup, if you click the image, both nextImage() and hideOverlay() are called. But what I want is for only nextImage() to be called.

问题是,使用这个设置,如果单击图像,将调用nextImage()和hideOverlay()。但我想要的只是下次调用()。

I know you can capture and cancel the event in the nextImage() function like this:

我知道您可以在nextImage()函数中捕获并取消事件,如下所示:

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

...But I want to know if there's a better AngularJS way of doing it that won't require me to prefix all of the functions on elements inside the overlay with this snippet.

…但是我想知道是否有更好的AngularJS方法,不需要我用这个代码段对覆盖层中的所有元素进行前缀。

9 个解决方案

#1


172  

What @JosephSilber said, or pass the $event object into ng-click callback and stop the propagation inside of it:

@JosephSilber说的,或者将$事件对象传递到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
}

#2


164  

Use $event.stopPropagation():

使用$ event.stopPropagation():

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

Here's a demo: http://plnkr.co/edit/3Pp3NFbGxy30srl8OBmQ?p=preview

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

#3


98  

I like the idea of using a directive for this:

我喜欢这样的想法:

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

Then use the directive like:

然后使用指令,如:

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

If you wanted, you could make this solution more generic like this answer to a different question: https://*.com/a/14547223/347216

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

#4


29  

Sometimes, it may make most sense just to do this:

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

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

I chose to do it this way because I didn't want myClickHandler() to stop the event propagation in the many other places it was used.

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

Sure, I could've added a boolean parameter to the handler function, but stopPropagation() is much more meaningful than just true.

当然,我可以向处理程序函数添加布尔参数,但是stopPropagation()比true更有意义。

#5


7  

This works for me:

这工作对我来说:

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

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

#6


4  

If you don't want to have to add the stop propagation to all links this works as well. A bit more scalable.

如果您不希望将停止传播添加到所有链接中,那么也可以这样做。更加可伸缩。

$scope.hideOverlay( $event ){

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

}

#7


0  

If you insert ng-click="$event.stopPropagation" on the parent element of your template, the stopPropogation will be caught as it bubbles up the tree, so you only have to write it once for your entire template.

如果你插入ng-click = " $事件。停止传播“在模板的父元素上,停止传播将被捕获,因为它在树中冒泡,所以您只需为整个模板编写一次。

#8


0  

You can register another directive on top of ng-click which amends the default behaviour of ng-click and stops the event propagation. This way you wouldn't have to add $event.stopPropagation by hand.

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

#9


0  

IN controller use

控制器使用

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

美元的范围。methodName = function(event) {event. stoppropagation ();}

#1


172  

What @JosephSilber said, or pass the $event object into ng-click callback and stop the propagation inside of it:

@JosephSilber说的,或者将$事件对象传递到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
}

#2


164  

Use $event.stopPropagation():

使用$ event.stopPropagation():

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

Here's a demo: http://plnkr.co/edit/3Pp3NFbGxy30srl8OBmQ?p=preview

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

#3


98  

I like the idea of using a directive for this:

我喜欢这样的想法:

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

Then use the directive like:

然后使用指令,如:

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

If you wanted, you could make this solution more generic like this answer to a different question: https://*.com/a/14547223/347216

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

#4


29  

Sometimes, it may make most sense just to do this:

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

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

I chose to do it this way because I didn't want myClickHandler() to stop the event propagation in the many other places it was used.

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

Sure, I could've added a boolean parameter to the handler function, but stopPropagation() is much more meaningful than just true.

当然,我可以向处理程序函数添加布尔参数,但是stopPropagation()比true更有意义。

#5


7  

This works for me:

这工作对我来说:

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

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

#6


4  

If you don't want to have to add the stop propagation to all links this works as well. A bit more scalable.

如果您不希望将停止传播添加到所有链接中,那么也可以这样做。更加可伸缩。

$scope.hideOverlay( $event ){

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

}

#7


0  

If you insert ng-click="$event.stopPropagation" on the parent element of your template, the stopPropogation will be caught as it bubbles up the tree, so you only have to write it once for your entire template.

如果你插入ng-click = " $事件。停止传播“在模板的父元素上,停止传播将被捕获,因为它在树中冒泡,所以您只需为整个模板编写一次。

#8


0  

You can register another directive on top of ng-click which amends the default behaviour of ng-click and stops the event propagation. This way you wouldn't have to add $event.stopPropagation by hand.

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

#9


0  

IN controller use

控制器使用

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

美元的范围。methodName = function(event) {event. stoppropagation ();}