将点击事件添加到元素,但不添加角度的子元素

Posted

技术标签:

【中文标题】将点击事件添加到元素,但不添加角度的子元素【英文标题】:Add click event to element, but not its children in angular 【发布时间】:2016-10-31 14:36:41 【问题描述】:

我知道这可以用 jQuery 来完成,如下所示:How to have click event ONLY fire on parent DIV, not children?

$('.foobar').on('click', function(e) 
  if (e.target !== this)
    return;

  alert( 'clicked the foobar' );
);

但在 Angular 中,this 关键字在我使用类似以下内容时未绑定到元素:

<div ng-dblclick="ctrl.doubleClickHandler($event)">
    parent, event should fire here.
    <div>child, event should not fire here.</div>
</div>

在我的控制器中:

this.doubleClickHandler = doubleClickHandler;
function doubleClickHandler(event) 
  console.log(this); // this binds to controller
  console.log(event);

事件触发,但是当我点击元素的子元素时,我需要阻止它触发。

我不想基于类或属性对event.target 的检查进行硬编码,因为以后可能会更改。有没有办法在 html 标记中实现这一点,或者在 javascript 中无需硬编码元素的类或属性(类似于在 jQuery 中绑定 this 关键字的技术)?

【问题讨论】:

为什么在 Angular 控制器中使用私有函数? @Maher 我的控制器中有this.doubleClickHandler = doubleClickHandler;,但这不是我认为的重点吗? @Maher 我被教导要通过 this.ctrlFunc() 而不是 $scope.cntrlFunc() 在控制器中保留不需要绑定到 $scope 私有的任何控制器逻辑。它仍然是公开的,因为您可以通过分配给控制器的名称来调用控制器内的函数。 我知道,我们可以将范围定义为控制器中的任何内容,但在此示例中,我们将函数定义为私有,因此我们无法获取控制台。 你在使用jqueryangular吗? 【参考方案1】:

您可以比较targetcurrentTarget。前者是被点击的元素,后者是带有handler的元素。

function doubleClickHandler(event) 
  if (event.target !== event.currentTarget) return;
  // do something

【讨论】:

谢谢。这正是我正在寻找的。另外,***.com/questions/10086427/… 很有帮助。 太棒了:),就这么简单 是的,这实际上不是特定于 Angular 的答案。在 Angular 中,如果您还想处理来自&lt;span&gt; 等内部非按钮元素的事件,您可以检查event.target 是否具有[ng-click] 等属性。 你用那个 currentTarget 救了我的命,谢谢【参考方案2】:

我想你可以试试这样的:

<div ng-dblclick="ctrl.doubleClickHandler($event) $event.stopPropagation()">

参考:What's the best way to cancel event propagation between nested ng-click calls?

【讨论】:

这不起作用。我认为这是因为孩子们拥有完全相同的事件侦听器,只是使用不同的event.target 触发。所以无论如何都会触发事件。【参考方案3】:

如果您使用jquery 试试这个,

<div class="foobar"> .foobar (alert)
      <span>child (no alert)</span>
</div>

$('.foobar').on('click', function(e) 
    if (e.target !== this)
      return;

    $scope.myFunc(e);
);


$scope.myFunc = function(e) 
     $scope.clicked = "Parent Cicked";
    $scope.$apply();
;

DEMO

这肯定不会导致良好的编程技能。因此,您可以使用angularJS 尝试以下示例

<div class="foobar" data-parent="true" ng-click="myFunc($event)"> .foobar (alert)
      <span>child (no alert)</span>
</div>

// add data attribute as data-parent="true"

$scope.myFunc = function(e) 
    if (! e.target.hasAttribute('data-parent'))
        return;

    $scope.clicked = "Parent Cicked";
;

//if clicked element has `data-parent` property do the things.

DEMO

【讨论】:

感谢您的回答,但我不想检查属性或类(请参阅问题描述)。否则,它会破坏在该特定元素上添加 ng-click 的目的,因为我可以将它添加到 body 并达到相同的效果。【参考方案4】:

我通过在您的示例中使用 jquery 创建指令来更新答案。

var app = angular.module("app", []);

        app.controller("controller", function ($scope) 
            var ctrl = this;


            ctrl.doubleClickHandler = function () 
                alert("parent clicked")
            
        );


        app.directive("directiveName", function () 
            return 
                restrict: "A",
                scope: 
                    click: "&"
                ,
                link: function (scope, element, attr) 

                    element.on('click', function (e) 
                        if (e.target !== this) 
                            return;
                         else 
                            scope.click()
                        
                    );

                
            
        )
.foobar span 
            background: red;
        
<!DOCTYPE html>
<html ng-app="app" ng-controller="controller as ctrl">
<head>
    <title></title>
</head>
<body>
    <div click="ctrl.doubleClickHandler()" directive-name class="foobar">

        parent

        <span>
            child
        </span>

    </div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

</body>
</html>

【讨论】:

嗨,你误解了我的问题,事件正在触发,但我只需要触发带有ng-dbclick 的元素,而不是它的子元素。 感谢您的新答案,但这有点过头了,我接受的答案要简单得多。

以上是关于将点击事件添加到元素,但不添加角度的子元素的主要内容,如果未能解决你的问题,请参考以下文章

js 为动态添加的元素绑定事件

以角度重新编译元素,但不重新绑定角度事件[重复]

vue中的点击事件

如何将点击事件添加到打字稿中动态添加的html元素

如何将点击事件添加到插入的元素

js删除一个ID元素的点击事件