2016-12-28 53 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