当前位置: 首页 > 知识库问答 >
问题:

指令,当单击元素外部时触发事件

廖君昊
2023-03-14

为什么我需要这个功能?我正在建立一个应用程序,在这个应用程序,有3下拉菜单,5下拉列表(喜欢选择)。所有这些都是角指令。让我们假设所有这些指令都是不同的。所以我们有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);
      })
    }
  }
})
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在我的应用程序中工作,我现在正在使用。但问题是它会导致性能问题。太多的点击事件处理每一个单一的点击在应用程序的任何地方。在我当前的情况下,有8个click事件与文档绑定,所以每个click执行8个函数。这导致我的应用程序非常慢,尤其是在IE8中。

那么有没有更好的解决办法呢?谢谢

共有1个答案

陈业
2023-03-14

我不会使用event.stoppropagation(),因为它会引起解决方案A中的问题。如果可能的话,我还会使用模糊和聚焦事件。当您的下拉列表附加到输入时,您可以在输入失去焦点时关闭它。

但是,在文档上处理click事件也不是很糟糕,所以如果您想避免多次处理同一个click事件,只需在不再需要它时将它与文档解除绑定即可。除了在下拉菜单外单击时要计算的表达式之外,指令还需要知道它是否处于活动状态:

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);
                }
            });
        }
    };
}]);

在使用指令时,只需提供如下所示的另一个表达式:

<your-dropdown click-anywhere-but-here="close()" is-active="isDropdownOpen()"></your-dropdown>
 类似资料:
  • 问题内容: 我知道有很多问题问类似的事情。但没人能真正解决我的问题。 我正在尝试建立一个指令,当在当前元素之外单击鼠标时,该指令将执行一个表达式。 为什么需要此功能?我正在构建一个应用程序,在此应用程序中,有3个下拉菜单,5个下拉列表(如所选)。所有这些都是角度指令。让我们假设所有这些指令都是不同的。因此,我们有8个指令。它们都需要相同的功能:在元素旁边单击时,需要隐藏下拉菜单。 我对此有2个解决

  • 问题内容: 现在,我有一个div,它基本上是一个巨大的正方形,在div内,我还有另一个div,它是简单的文本,上面写着“ Upload File”,同时还有一个隐藏的input type = file元素。当用户按下div时,我要触发文件上传元素。到目前为止,我想出的代码是: 因此,我在CSS中将文件输入元素设置为。一旦他们在div id =“ test”中的任意位置单击,我想触发对文件上传元素的

  • 问题内容: 我正在尝试使用复选框和过滤器选项创建多选下拉列表。我试图隐藏列表,但我在外面单击却无法弄清楚。感谢你的帮助。 http://plnkr.co/edit/tw0hLz68O8ueWj7uZ78c 问题答案: 请注意,打开第二个弹出窗口(在具有多个选择的页面上)时,您的解决方案(问题中提供的Plunker)不会关闭其他框的弹出窗口。 通过单击一个框打开一个新的弹出窗口,单击事件将始终停止。

  • 如果click在具体的DOM元素之外,我使用下面的指令来检测和隐藏块: 我已将此指令应用于元素: 部件代码为: 问题是当我调用click时,我设置了< code >这个。_searchContentOpen设置为真/假。 视情况而定,我在应用指令的地方显示块。但是当ngIF工作时,指令也总是同步工作。所以结果块永远不会显示。 如何修复它?

  • 问题内容: 我试图用Javascript编写视频扑克游戏,以降低其基础知识,但是我遇到了一个问题,其中jQuery click事件处理程序多次触发。 它们被附加到用于下注的按钮上,并且对于在游戏过程中第一手下注(仅触发一次)非常有效。但是在秒针下注中,每次按下一个下注或下注按钮都会触发两次点击事件(因此,每次按下正确的赌注量是两次)。总体而言,在按一次下注按钮时,触发单击事件的次数遵循此模式序列的

  • 问题内容: 如何检测元素外部的点击?我正在使用Vue.js,因此它将不在我的模板元素之外。我知道如何在Vanilla JS中做到这一点,但是当我使用Vue.js时,我不确定是否有更合适的方法来做到这一点? 我想我可以使用更好的方法来访问元素? 问题答案: 只需设置一次自定义指令即可很好地解决: 用法: 在组件中: