当前位置: 首页 > 面试题库 >

在元素外部单击时触发事件的指令

邹宏峻
2023-03-14
问题内容

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

我正在尝试建立一个指令,当在当前元素之外单击鼠标时,该指令将执行一个表达式。

为什么需要此功能?我正在构建一个应用程序,在此应用程序中,有3个下拉菜单,5个下拉列表(如所选)。所有这些都是角度指令。让我们假设所有这些指令都是不同的。因此,我们有8个指令。它们都需要相同的功能:在元素旁边单击时,需要隐藏下拉菜单。

我对此有2个解决方案,但都遇到了问题:

解决方案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的示例:单击此处

解决方案:如果页面中只有一个指令,但我的应用程序中没有,则可以正常工作。因为它可以防止冒泡,所以当我单击dropdown1时,显示dropdown1,然后单击dropdown2,单击event
be prevent,因此即使我在dropdown1之外单击,dropdown1仍显示在那里。

解决方案B在我现在正在使用的应用程序中运行。但是问题是它导致性能问题。在应用程序中任何位置的每次单击都会处理太多单击事件。在我当前的情况下,有8个click事件与文档绑定,因此每次单击都执行8个功能。这导致我的应用程序运行缓慢,尤其是在IE8中。

那么有没有更好的解决方案呢?谢谢


问题答案:

我不会使用event.stopPropagation(),因为它确实会引起您在解决方案A中看到的那种问题。如果可能,我还将求助于模糊和聚焦事件。将下拉列表附加到输入后,可以在输入失去焦点时将其关闭。

但是,处理文档上的单击事件也不是很糟糕,因此,如果要避免多次处理同一单击事件,只需在不再需要它时将其与文档解除绑定即可。除了在下拉列表之外单击时要评估的表达式之外,该指令还需要知道它是否处于活动状态:

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>

我尚未测试您的onClick功能。我认为它按预期工作。希望这可以帮助。



 类似资料:
  • 为什么我需要这个功能?我正在建立一个应用程序,在这个应用程序,有3下拉菜单,5下拉列表(喜欢选择)。所有这些都是角指令。让我们假设所有这些指令都是不同的。所以我们有8个指令。它们都需要一个相同的功能:当点击元素的侧面时,需要隐藏下拉菜单。 我有两个解决方案,但都有问题: 解决方案A: 解决方案B在我的应用程序中工作,我现在正在使用。但问题是它会导致性能问题。太多的点击事件处理每一个单一的点击在应用

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

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

  • 问题内容: 似乎是一个简单的问题,但解决其他问题的方法似乎对我没有用。 试图通过单击按钮来触发AJAX请求,但似乎并未触发。 HTML示例 javascript 问题答案: 您拥有的代码在拨弄中工作得很好。初始页面加载后,按钮是否通过AJAX动态呈现? 用 代替

  • 示例代码: 我能够获得所选行的行索引,以获得精确的列数据。 上面的tr点击事件就可以了。 我现在的问题是,当单击表行内的锚链接时,如何触发此tr绑定事件? 目标:首先获得(在tr.bind click事件上处理),然后再处理锚定链接上的其余代码? 我试图在锚链接click事件中复制tr click函数,但在unitno上得到了未定义的值。查看我的代码: 测试代码:http://jsfidle.ne

  • 我在角度组件上有一个单击事件: 请参阅在线演示:https://stackblitz.com/edit/angular-ivy-zxmsnc?file=src/app/app.component.ts 为什么是