javascript - 'destroyed' Controller 中的 Angular $rootScope $on 监听器继续运行

标签 javascript angularjs lifecycle watch ng-view

我在 index.html 中使用 ng-view 指令设置了我的 Angular 应用程序, View 使用 $routeProvider 配置配置,每个 View 都有自己的 Controller 。在一个 View Controller 中,我有一个 $rootScope.$on 监听器来监视事件。我希望这个监听器在我更改 View 时不再运行,但事实并非如此。 watch 在触发时仍会继续调用代码,即使我切换到不再使用该 Controller 的 View 也是如此。

我已经设置了一些测试代码来监听$destroy事件,我可以看到$destroy事件被触发了,但是监听函数仍然运行。我已经在 watch 函数和 $destroy 事件监听器中打印出 $scope.$id,我可以看到 ID 匹配。因此,似乎即使在特定范围发生 $destroy 事件之后,其上的 $on 监听器仍会继续运行。为什么会这样?我的印象是当导航到不同的 View 时,或者在任何情况下 Controller 被销毁,然后它的监听器被清除。

请联系: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);
});

上一个答案

您应该确保在您的 Controller 范围被销毁时解除绑定(bind)。

创建 watch 时,angular 会为您创建的 watch 返回一个解除绑定(bind)函数。这很好地涵盖了here .

创建对您创建的 watch 的引用:

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

像以前一样注意作用域的破坏,但是在那里调用你的unbinder

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

调用unbinder 函数后,您的 watch 将被删除。

关于javascript - 'destroyed' Controller 中的 Angular $rootScope $on 监听器继续运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41365958/

相关文章:

symfony - 访问事件订阅者内部的服务

javascript - slideDown 时向下推底部 div

javascript - ng-if indexOf 与 JSON 数组

angularjs - 无法从状态 'state1' 解析 'state2'

android - 应用程序 + Activity + onResume == 空指针异常

java - Apache Tomcat Servlet 线程未完成

javascript - 将输入值与数据库 Coldfusion 中的值进行比较

Javascript 代码执行延迟

javascript - puppeteer 系统要求

javascript - 如何以更有效的方式组合 _.map 和 _.filter?