角点击元素事件之外 [英] Angular Click outside of an element event

查看:91
本文介绍了角点击元素事件之外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有很多问题问类似的事情。但没有人真正解决我的问题。

I know there are many questions ask similar thing. But no one really solve my issue.

我试图建立将执行一个前pression的指令时,鼠标点击当前元素外面。

I'm trying to build an directive which will execute an expression when mouse click outside the current element.

为什么我需要这个功能呢?我建立一个应用程序,在这个程序中,有3下拉菜单中,5下拉列表(如选择)。所有这些都是角指令。让我们假定所有这些指令是不同的。因此,我们有8个指令。和所有的人都需要一个相同功能:当点击出方的元素,需要隐藏下拉

Why I need this function? I'm building an app, in this app, there are 3 dropdown menu, 5 dropdown list(like chosen). All these are angular directives. Let's assume all these directives are different. So we have 8 directives. And all of them need a same function: when click out side the element, need hide the dropdown.

我对这个解决方案2,但都得到了问题:

I have 2 solutions for this, but both got issue:

解决方案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);
      })
    }
  }
})

下面是一个解决方案的例子:点击这里

Here is an example for solution A: click here

当您单击第一个下拉列表,然后工作,然后单击第二个输入时,首先应躲在但不是。

When you click the first dropdown, then working, then click second input, the first should hide but not.

解决方案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:点击这里

解决方案的一个工作,如果在该网页,但不是在我的应用程序只是一个指令。因为它是prevent冒泡,所以先当我点击dropdown1,显示dropdown1,然后单击dropdown2,单击事件是prevent,所以dropdown1仍呈现甚至有我点击dropdown1之外。

Solution A working if there is just one directive in the page but not in my app. Because it's prevent bubbling, so first when I click on dropdown1, show dropdown1, then click on dropdown2, click event be prevent, so dropdown1 still showing there even I click outside the dropdown1.

解决方案B在我的应用我使用的是现在这工作。但问题是它会导致性能问题。太多的点击事件上的任何地方应用的每一个点击处理。在我目前的情况下,有8 click事件绑定文件,那么每一次点击执行8个功能。这引起我的应用程序很慢,尤其是在IE8。

Solution B working in my app which I'm using now. But the issue is it's cause a performance issue. Too many click event be handled on every single click on anywhere in the app. In my current case, there are 8 click event bind with document, so every click execute 8 functions. Which cause my app very slow, especially in IE8.

那么,有没有这方面的任何更好的解决方案?谢谢

So is there any better solution for this? Thanks

推荐答案

我不会用event.stopPropagation(),因为它会导致你究竟在溶液A.如果有可能看到什么样的问题,我也不惜以模糊和焦点事件。当你的下拉列表连接到一个输入,可以在输入失去焦点关闭它。

I would not use event.stopPropagation() since it causes exactly the kind of problems you see in solution A. If possible, I would also resort to blur and focus events. When your dropdown is attached to an input, you can close it when the input loses the focus.

然而,在文件处理click事件不是那么糟糕,所以如果你想避免处理相同的单击事件几次,只是从文件解除它的时候已经不再需要它。除了前pression下拉外点击时被评估,该指令需要知道它是否处于活动状态:

However, handling click events on the document is not so bad either, so if you want to avoid handling the same click event several times, just unbind it from the document when it is not needed anymore. In addition to the expression being evaluated when clicking outside the dropdown, the directive needs to know whether it is active or not:

app.directive('clickAnywhereButHere', ['$document', function ($document) {
    return {
        link: function postLink(scope, element, attrs) {
            var 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)
                }
            }
            scope.$watch(attrs.isActive, function(newValue, oldValue) {
                if (newValue !== oldValue && newValue == true) {
                    $document.bind('click', onClick);
                }
                else if (newValue !== oldValue && newValue == false) {
                    $document.unbind('click', onClick);
                }
            });
        }
    };
}]);

在使用的指令,只是提供了另一种前pression是这样的:

When using the directive, just provide another expression like this:

<your-dropdown click-anywhere-but-here="close()" is-active="isDropdownOpen()"></your-dropdown>

我没有测试过你的onClick功能。我认为它工作正常。希望这有助于。

I have not tested your onClick function. I assume it works as expected. Hope this helps.

这篇关于角点击元素事件之外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆