如何在AngularJS中销毁$emit和$broadcast事件?

25 浏览
0 Comments

如何在AngularJS中销毁$emit和$broadcast事件?

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

根据这里的答案,我创建了一些$broadcast事件,以允许在主$rootScope中的操作关闭子$scopes中的弹出框。但是,我想确保清理所有事件,不留下任何不应该存在的东西。

我有一个弹出框指令,一旦弹出框被激活,我会发送:

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

回到弹出框指令,这是我的bodyClick监听器:

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

^我也在那里尝试了杀死bodyClick事件的代码,但是没有效果 🙁

如下所示,我已经从$$listenerCount中移除了bodyClick和popoverOpen($$listener对象中从未有任何东西)。

但是,即使popoverOpen应该已被删除,用户仍可以访问主应用程序rootScope中的vs.bodyClick()函数。


因此,在首次加载时:

  • 如果用户在不打开任何弹出框的情况下单击,将不会捕获/传输bodyClick事件
  • 打开弹出框后,bodyClick变为活动状态
  • 如果用户单击主体,该事件被发送出去并关闭弹出框
  • 然而,现在即使没有打开任何弹出框,如果用户单击主体,则该bodyClick事件仍然会被发送出去

\"enter

如何正确地移除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

admin 更改状态以发布 2023年5月23日
0
0 Comments

关于您的代码片段,有一些需要注意的地方:

  1. 您的控制器没有超出作用域,因此没有触发$destroy事件。
  2. 您在监听$destroy事件,但尝试触发destroy,这是不一样的。移除监听器中的$符号,就能看到回调函数在执行了。
  3. 由于subControllermainController的子级,摧毁主控制器,两个控制器也都被销毁了,包括按钮和其他所有对象。此现象可在此代码片段中看到。

因此,为了激发虚假的$destroy事件,我将其改为仅监听destroy事件。

然后,我没有调用您的解除绑定方法,因为在这种情况下我们并没有真正摧毁任何对象,而是仅仅将bodyClick函数进行了替换,因为它被绑定在了上。

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

这样做好像达到了预期效果。这是更新后的代码片段

更新:我发现了一点,那就是它一直在不断添加监听器……!destroy监听器出现在按钮回调函数中。因此,每次按下按钮都会添加一个新的回调函数。我将destroy监听器移到了popover监听器之外。现在已经没有内存泄漏的问题了!

0