如何破坏AngularJS中的$ emit和$ broadcast事件?

时间:2015-05-15 19:21:01

标签: javascript angularjs angularjs-directive angularjs-scope

Plnkr示例构建:http://plnkr.co/edit/gB7MtVOOHH0FBJYa6P8t?p=preview

Following the answer here,我创建了一些$broadcast个事件,以允许主$scope中的操作关闭子$scopes中的弹出窗口。但是我想确保我清理所有的事件而不会有任何不应该留下的事情。

我有一个popover指令,一旦弹出窗口被激活,我发出:

vs.$emit('popoverOpen');

然后在主应用程序模块($ rootScope)中,我在这里听取它:

vs.$on('popoverOpen',function(events,data) {

    // if 'popoverOpen' is heard, then activate this function
    // which on click $broadcasts out even 'bodyClick'
    // but also destroy the 'popoverOpen' event
    vs.bodyClick = function() {
        $rootScope.$broadcast('bodyClick');
        $rootScope.$$listenerCount.popoverOpen=[];
    };
});

回到popover指令中,这是我的bodyClick听众:

vs.$on('bodyClick', function() {
    vs.searchPopoverDisplay = false;
    $rootScope.$$listenerCount.bodyClick=[];
});

^我也有代码试图杀死bodyClick事件,但无济于事:(

如下所示,我已从bodyClick中移除了popoverOpen$$listenerCount$$listener对象中没有任何内容。

但是,即使vs.bodyClick()已被删除,用户仍然可以访问主应用rootScope中的popoverOpen功能。

首次加载:

  • 如果用户点击而不打开任何弹出窗口,则永远不会捕获/传输bodyClick
  • 打开popover后,bodyClick处于活动状态
  • 如果用户点击了正文,那么该事件将被发送并关闭popover
  • 但是,现在即使没有弹出窗口,如果用户点击bodyClick事件不断发送的正文

enter image description here

在发送bodyClick事件以关闭弹出窗口后,您如何正确删除事件?

更新 我也尝试了这个(https://github.com/toddmotto/angularjs-styleguide#publish-and-subscribe-events),但是当弹出窗口关闭并且据说被破坏后,bodyClick事件仍然会被发送出来。

仍会调用popoverDirective函数:

vs.$on('bodyClick', function() {

    console.log('bodyClick received ...');
    console.log($rootScope.$$listener);
    console.log($rootScope.$$listenerCount);

    vs.searchPopoverDisplay = false;

    var unbind = $rootScope.$on('popoverOpen', []);
    vs.$on('$destroy', unbind);
    // $rootScope.$$listenerCount.bodyClick=[];
});

enter image description here

1 个答案:

答案 0 :(得分:3)

关于你的傻瓜的几点说明:

  1. 您的控制器都没有超出范围,因此它们都没有发射 $destroy
  2. 您正在聆听$destroy但正在尝试 发出destroy,它不是一样的。从中删除$ 听众,你会看到回调正在运行。
  3. 因为subControllermainController的孩子,所以摧毁主要人员会破坏两者并停止按钮,以及其他所有内容。此行为显示在this plunkr
  4. 因此,为了让伪 - $destroy能够ping,我将其更改为只监听destroy

    然后,我没有打电话给你的unbind,因为我们实际上并没有$destroy任何事情,因此我无法在这种情况下工作,我只是替换了bodyClick函数,因为它绑定到<body>

    $scope.$on('destroy', function() {
      $scope.bodyClick = angular.noop();
    });
    

    这似乎有预期的效果。 已更新 Plunkr here

    更新:我发现为什么它会无限期地添加听众......! destroy侦听器 in 按钮回调。所以按下每个按钮会添加另一个回调。我将destroy侦听器移到popover侦听器之外。没有更多的内存泄漏!