Angular $ rootScope $ on在“销毁"控制器中的侦听器继续运行 [英] Angular $rootScope $on listeners in 'destroyed' controller keep running

查看:278
本文介绍了Angular $ rootScope $ on在“销毁"控制器中的侦听器继续运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在index.html中用ng-view指令设置了我的角度应用程序,其中的视图使用$ routeProvider config配置,每个视图都有其自己的控制器.在一个视图控制器中,我有一个$ rootScope.$ on侦听器,用于监视事件.我希望在更改视图时不再运行该侦听器,但事实并非如此.即使我已切换到不再使用该控制器的视图,手表在被触发时仍会继续调用代码.

我已经设置了一些测试代码来侦听$ destroy事件,并且可以看到$ destroy事件正在被触发,但是侦听器功能仍在运行.我已经在watch函数和$ destroy事件监听器中打印了$ scope.$ id,并且我看到ID匹配.因此,即使在特定范围内发生$ destroy事件之后,它上的$ on侦听器仍然保持运行.为什么会这样呢?我的印象是,当导航到其他视图时,或者在任何情况下,控制器都被销毁,则清除了其侦听器.

Plnkr: http://plnkr.co/edit/TxssxQJY5PVLTAIAr4xD?p=preview

var animateApp = angular.module('animateApp', ['ngRoute', 'ngAnimate']);

animateApp.config(function($routeProvider) {
    $routeProvider
        .when('/', {
            templateUrl: 'page-home.html',
            controller: 'mainController'
        })
        .when('/about', {
            templateUrl: 'page-about.html',
            controller: 'aboutController'
        })
        .when('/contact', {
            templateUrl: 'page-contact.html',
            controller: 'contactController'
        });

});

angular.module('animateApp').service('service', ['$interval', '$rootScope', service]);
function service ($interval, $rootScope) {
    var service = {};
    service.abc = 1;
        $interval(function() {
        service.abc++;
        $rootScope.$broadcast('service.abc', service.abc);
    }, 500);

    return service;

}


animateApp.controller('mainController', function($scope, $rootScope, service) {
    $scope.pageClass = 'page-home';
    $scope.$on('$destroy', function iVeBeenDismissed() {
                        console.log('goodbye ' + $scope.$id);
      // release resources, cancel request...
    })

    $rootScope.$on('service.abc', function (newval) {
        console.log($scope.$id);
    })
});

animateApp.controller('aboutController', function($scope) {
    $scope.pageClass = 'page-about';
});

animateApp.controller('contactController', function($scope) {
    $scope.pageClass = 'page-contact';
});

解决方案

因此,问题已完全更改,因此上下文完全不同,因此我以前的回答不再与问题真正相关,只是它的用法完全相同方式.

您可以按照以下我的回答相同的方式注销听众的注册.

$rootScope.$on()返回注销功能.

因此,您的mainController可以重写为:

animateApp.controller('mainController', function($scope, $rootScope, service) {
    $scope.pageClass = 'page-home';
    var unregister = $rootScope.$on('service.abc', function (newval) {
        console.log($scope.$id);
    });
    $scope.$on('$destroy', unregister);
});

上级答案

您应该确保在破坏控制器范围时解除对手表的绑定.

在创建手表时,angular为您创建的手表返回一个解除绑定的功能. 此处.

创建对您创建的手表的引用:

var unbinder = $scope.$watch("foo.bar", doStuff);

照原样监视示波器的破坏,但在此处致电unbinder.

$scope.$on("$destroy", function(){
    if(typeof unbinder === "function")
        unbinder();
});

一旦调用了unbinder函数,您的手表将被删除.

I have my angular app set up with an ng-view directive in the index.html, with views configured with $routeProvider config and each view having its own controller. In one view controller, I have a $rootScope.$on listener that watches for events. I expect this listener to no longer run when I change views, but this is not the case. The watch still keeps calling code when it is triggered, even when I have switched to a view that is no longer using that controller.

I have set up some test code to listen to the $destroy event, and I can see that the $destroy event is being triggered, but the listener function still runs. I have printed out $scope.$id in both the watch function and the $destroy event listener, and I can see that the IDs match. So it seems that even after the $destroy event occurs for the specific scope, the $on listener on it still keep running. Why is this the case? I was under the impression that when navigating to a different view, or in any case the controller is destroyed, then listeners for it are cleared.

Plnkr: http://plnkr.co/edit/TxssxQJY5PVLTAIAr4xD?p=preview

var animateApp = angular.module('animateApp', ['ngRoute', 'ngAnimate']);

animateApp.config(function($routeProvider) {
    $routeProvider
        .when('/', {
            templateUrl: 'page-home.html',
            controller: 'mainController'
        })
        .when('/about', {
            templateUrl: 'page-about.html',
            controller: 'aboutController'
        })
        .when('/contact', {
            templateUrl: 'page-contact.html',
            controller: 'contactController'
        });

});

angular.module('animateApp').service('service', ['$interval', '$rootScope', service]);
function service ($interval, $rootScope) {
    var service = {};
    service.abc = 1;
        $interval(function() {
        service.abc++;
        $rootScope.$broadcast('service.abc', service.abc);
    }, 500);

    return service;

}


animateApp.controller('mainController', function($scope, $rootScope, service) {
    $scope.pageClass = 'page-home';
    $scope.$on('$destroy', function iVeBeenDismissed() {
                        console.log('goodbye ' + $scope.$id);
      // release resources, cancel request...
    })

    $rootScope.$on('service.abc', function (newval) {
        console.log($scope.$id);
    })
});

animateApp.controller('aboutController', function($scope) {
    $scope.pageClass = 'page-about';
});

animateApp.controller('contactController', function($scope) {
    $scope.pageClass = 'page-contact';
});

解决方案

So the question was completely changed so that the context was entirely different, so my previous answer no longer relates to the question really, except that it applies quite the same way.

You can unregister your listener in the same respect as my answer below.

$rootScope.$on() returns an unregister function.

Therefore, your mainController can be re-written as:

animateApp.controller('mainController', function($scope, $rootScope, service) {
    $scope.pageClass = 'page-home';
    var unregister = $rootScope.$on('service.abc', function (newval) {
        console.log($scope.$id);
    });
    $scope.$on('$destroy', unregister);
});

PREVIOUS ANSWER

You should make sure that you unbind your watch when the scope of your controller is destroyed.

When creating a watch, angular returns an unbinding function for the watch you created. This is covered pretty well here.

Create a reference to the watch you create:

var unbinder = $scope.$watch("foo.bar", doStuff);

Watch for your scope's destruction as you were, but call your unbinder there.

$scope.$on("$destroy", function(){
    if(typeof unbinder === "function")
        unbinder();
});

Once your unbinder function is called, your watch will be removed.

这篇关于Angular $ rootScope $ on在“销毁"控制器中的侦听器继续运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆