【问题标题】: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吗?

标签: javascript angularjs


【解决方案1】:

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

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

【讨论】:

  • 谢谢。这正是我正在寻找的。另外,stackoverflow.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 的元素,而不是它的子元素。
  • 感谢您的新答案,但这有点过头了,我接受的答案要简单得多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-07
  • 1970-01-01
相关资源
最近更新 更多