我知道有很多类似的问题,但没有一个真正解决我的问题。
我正在尝试构建一个指令,当鼠标点击当前元素外部时执行一个表达式。
为什么需要这个功能呢?我正在构建一个应用程序,在这个应用程序中有3个下拉菜单,5个下拉列表(类似于chosen)。所有这些都是Angular指令。假设所有这些指令都不同。所以我们有8个指令。并且所有这些指令都需要一个相同的功能: 当点击元素外部时,需要隐藏下拉菜单。
我有两种解决方案,但都有问题:
方案A:
app.directive('clickAnywhereButHere', function($document){
return {
restrict: 'A',
link: function(scope, elem, attr, ctrl) {
elem.bind('click', function(e) {
// this part keeps it from firing the click on the document.
e.stopPropagation();
});
$document.bind('click', function() {
// magic here.
scope.$apply(attr.clickAnywhereButHere);
})
}
}
})
这是解决方案A的示例:点击此处
当您单击第一个下拉菜单,然后进行操作,再单击第二个输入框时,第一个应该隐藏但未隐藏。
解决方案B:
app.directive('clickAnywhereButHere', ['$document', function ($document) {
directiveDefinitionObject = {
link: {
pre: function (scope, element, attrs, controller) { },
post: function (scope, element, attrs, controller) {
onClick = function (event) {
var isChild = element.has(event.target).length > 0;
var isSelf = element[0] == event.target;
var isInside = isChild || isSelf;
if (!isInside) {
scope.$apply(attrs.clickAnywhereButHere)
}
}
$document.click(onClick)
}
}
}
return directiveDefinitionObject
}]);
以下是解决方案B的示例:点击此处
如果页面中只有一个指令,则解决方案A可以正常工作,但在我的应用程序中无法正常工作。因为它会防止事件冒泡,因此当我单击dropdown1时,首先显示dropdown1,然后单击dropdown2,单击事件被阻止,因此dropdown1仍然显示在那里,即使我在dropdown1外部单击。
解决方案B在我现在使用的应用程序中有效。但问题是它会导致性能问题。每次在应用程序的任何位置单击时,都会处理过多的单击事件。在我的当前情况下,有8个单击事件绑定到文档上,因此每次单击都会执行8个函数。这导致我的应用程序非常慢,特别是在IE8中。
所以,有没有更好的解决方案?谢谢