2016-12-28 76 views
1

我有我的角应用程序在index.html中使用ng-view指令设置,视图使用$ routeProvider config配置,每个视图都有自己的控制器。在一个视图控制器中,我有一个监听器监视事件的$ rootScope。$。我希望这个监听者在我改变视图时不再运行,但事实并非如此。即使当我切换到不再使用该控制器的视图时,手表仍会在触发时保持调用代码。

我已经设置了一些测试代码来侦听$ 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'; 
}); 
+1

你可以通过[plunk](http://plnkr.co)或[小提琴](http://jsfiddle.net) – Minato

+0

来演示你的逻辑/问题请提供[mcve] – TheSharpieOne

+0

对不起,实际上它是在监听器上使用$ rootScope。$。我将用plnkr进行更新并进行编辑。 – dz210

回答

0

你应该在你的控制器中添加$destroy事件侦听器:

scope.$on('$destroy', function() { 
     element.off('blur'); // example 
     element = null; 
    }); 

有了这个,你将手动确保不会有更积极的$观察家上无效的控制器

3

所以这个问题被彻底改变了,所以上下文完全不同,所以我以前的回答不再与真正的问题有关,除了它应用的方式完全相同。

您可以像我的答案一样注销您的听众。

$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', function iVeBeenDismissed() { 
     unregister(); 
    }); 
}); 

以前的答案

你应该确保你拆散你的手表时,你的控制器的范围被破坏。

创建手表时,角度会为您创建的手表返回一个解除绑定功能。这覆盖得很好here

创建以创建表的引用:

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

关注你的范围的破坏为你,而是打电话给你unbinder那里。

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

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

+0

@ dz210请重新审查我的答案,因为我已将其更改为符合您的更改。请在将来更详细地提出问题。 – WebWanderer

+0

感谢您的回复,但我的问题是为什么听众在控制器看起来被破坏后继续运行,所以我不是在寻找解决方案,而是解释发生了什么。不幸的是,我已经意识到如何注销听众和手表。我的问题更具理论性,因为我无法在角度文档中找到答案。 – dz210

+0

然后@ dz210你的答案是'$ rootScope'对你的整个应用程序来说是全局的,注册一个监听器对'$ rootScope'没有绑定你的独立范围,除非你手动这样做。如果要将侦听器放置在隔离范围内,例如在'$ scope。$ on'中,那么当范围为时,您的侦听器将被销毁。你的问题没有说明你想知道为什么比你想的更多。 – WebWanderer