将点击事件添加到元素,但不添加角度的子元素
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 私有的任何控制器逻辑。它仍然是公开的,因为您可以通过分配给控制器的名称来调用控制器内的函数。
我知道,我们可以将范围定义为控制器中的任何内容,但在此示例中,我们将函数定义为私有,因此我们无法获取控制台。
你在使用jquery
和angular
吗?
【参考方案1】:
您可以比较target
和currentTarget
。前者是被点击的元素,后者是带有handler的元素。
function doubleClickHandler(event)
if (event.target !== event.currentTarget) return;
// do something
【讨论】:
谢谢。这正是我正在寻找的。另外,***.com/questions/10086427/… 很有帮助。 太棒了:),就这么简单 是的,这实际上不是特定于 Angular 的答案。在 Angular 中,如果您还想处理来自<span>
等内部非按钮元素的事件,您可以检查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
这肯定不会导致良好的编程技能。因此,您可以使用angular
和JS
尝试以下示例
<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
的元素,而不是它的子元素。
感谢您的新答案,但这有点过头了,我接受的答案要简单得多。以上是关于将点击事件添加到元素,但不添加角度的子元素的主要内容,如果未能解决你的问题,请参考以下文章