Angular:在指令中解开事件并不能完全解开



我们有一个指令显示弹出窗口,在弹出窗口中,加载了模板,并带有一个指令,该指令捕获文档中的所有单击。

发生这种情况时,它会广播一个事件以关闭弹出窗口,并在 $document上解开事件。

这是捕获文档点击的指令。

aOS.directive('catchOutsideClick',
    [
        '$document',
        'eventsService',
        function CatchOutsideClickDirective($document, eventsService) {
            var CatchClick = function CatchClick(scope, element, attrs) {
                // Check if there was clicked on parent or one of its children
                function isDescendant(parent, child) {
                    var node = child.parentNode;
                    while (node !== null) {
                        if (node === parent) {
                            return true;
                        }
                        node = node.parentNode;
                    }
                    return false;
                }
                // Done clicking
                var onOutsideClick = function onOutsideClick(event) {
                    var clickedItem = event.target;
                    if (!isDescendant(element[0], clickedItem) && element[0] !== clickedItem) {
                        eventsService.publish('clicked-outside-popup', element[0]);
                        $document.unbind('click', onOutsideClick);
                    }
                };
                // Catch clicks!
                $document.bind('click', onOutsideClick);
            };
            return {
                restrict: 'A',
                scope: false,
                link: CatchClick
            };
        }
    ]
);

这是加载弹出窗口的HTML:

<div id="header" ng-controller="framework.header">
    <div data-ng-include="popupTemplate"></div>
</div>

为了简单起见,让我们声明控制器framework.header$scope.popupTemplate切换到下面显示的HTML的路径:

<div ng-controller="user.profle" catch-outside-click>
    <!-- loads of content -->
</div>

模板的包含似乎可以很好地工作,但是这是我们现在看到的行为:

  1. 您单击切换popupTemplate的按钮,然后将其加载到弹出窗口中。
  2. 可以很好地发射赶上旁边单击指令,并在文档上绑定单击器
  3. 弹出窗口内部的单击无济于事(在指令中对此进行了测试),但是弹出窗口外的单击弹出窗口很好地关闭了弹出窗口,这是因为它广播了捕获在Header Controller中的事件。
  4. 单击页面中的任何地方不会再次触发指令,因此我们认为它是正确的。
  5. 除非您单击按钮再次打开弹出窗口。这似乎都绑定了一个新文档点击事件,但也立即触发了clickhandler(这使我认为它触发了第一个ClickHandler)。

我目前不知道如何测试它是触发第一个还是第二个点击手。

任何人都知道我如何缩小这个问题,要么我在做完全错误的事情,要么指向我如何调试此问题以查看触发哪个EventHandler。

我们现在能够解决此问题:

aOS.directive('catchOutsideClick',
[
    '$document',
    'eventsService',
    function CatchOutsideClickDirective($document, eventsService) {
        ...
        setTimeout( function() {
            $document.bind('click', onOutsideClick);
        }, 0);
        ...
    }
]);

看起来settimeout内部的代码(绑定到点击)在下一个"周期"中执行(尽管超时设置为0),在其中单击以包含模板在同一(以前)中处理模板循环作为接口指令初始化的位置。至少在调查这个问题时我会感到这种感觉。

如果有人可以确认或具有更合理的解释(也许是更合乎逻辑的解决方案),我们仍然渴望学习: - )

相关内容

  • 没有找到相关文章

最新更新