2016-12-28 9 views
1

У меня есть мое угловое приложение, настроенное с директивой ng-view в index.html, с представлениями, настроенными с конфигурацией $ routeProvider, и каждый вид имеет свой собственный контроллер. В одном контроллере представления у меня есть $ rootScope. $ On listener, который следит за событиями. Я ожидаю, что этот слушатель больше не будет работать, когда я изменю представления, но это не так. Часы все еще продолжают вызывать код, когда он запускается, даже когда я переключился на представление, которое больше не использует этот контроллер.

Я установил некоторый тестовый код для прослушивания события $ destroy, и я вижу, что событие $ destroy запускается, но функция прослушивателя все еще работает. Я распечатал $ scope. $ Id как в функции часов, так и в прослушивателе событий $ destroy, и я вижу, что идентификаторы совпадают. Таким образом, кажется, что даже после того, как событие $ 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'; 
}); 
+0

с $ rootScope. $ на слушателе. Я буду обновлять с помощью plnkr и редактировать. – TheSharpieOne

+0

Извините, на самом деле это так, что вы можете продемонстрировать свою логику/проблему через [plunk] (http://plnkr.co) или [скрипка] (http://jsfiddle.net) – dz210

+0

Возможный дубликат [Как я могу отменить регистрацию вещательного события на корневой каталог в AngularJS?] (Http://stackoverflow.com/questions/18856341/how-can-i-unregister-a-broadcast-event-to-rootscope-in -angularjs) – WebWanderer

ответ

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

 Смежные вопросы

  • Нет связанных вопросов^_^