Angular.js $destroy event - следует ли вручную отменить привязку?

Я пытаюсь выяснить, может ли база angular автоматически отвязывать наблюдения и события сферы видимости, связанные с $scope.$on(...) или $scope.$watch(...), когда область действия уничтожена?

Предположим, что у меня есть следующий код:

$scope.$on('someEvents', handleSomeEvent);
$scope.$watch('someProperty', handleSomePropertyChange);

Нужно ли вручную отключать эти наблюдатели и события, когда в области событий запускается событие $destroy?

Ответ 1

Согласно Angular документации по $scope:

'$ destroy()' необходимо вызывать в области, когда требуется, чтобы область действия и ее дочерние области были окончательно отделены от родителя и, таким образом, перестали участвовать в обнаружении изменения модели и уведомлении слушателя, вызвав.

Также

Удаление также подразумевает, что текущая область имеет право на сбор мусора.

Итак, кажется, что при вызове $destroy() все наблюдатели и слушатели удаляются, а объект, который представляет область видимости, становится eligible for garbage collection.

Если мы посмотрим на destroy() исходный код, мы увидим строку:

forEach(this.$$listenerCount, bind(null, decrementListenerCount, this));

который должен удалить всех слушателей.

Как упоминалось в @glepretre, это относится к наблюдателям и слушателям в контроллере. Одна и та же страница документа, указанная выше, говорит, что:

Обратите внимание, что в AngularJS также существует событие $destroy jQuery, которое может использоваться для очистки привязок DOM до удаления элемента из DOM.

Итак, если у вас есть конкретные слушатели в директивах, вы должны слушать событие $destroy и выполнять необходимую очистку самостоятельно

Ответ 2

Если область действия находится в контроллере, angular отключите для вас. Кроме того, вы можете отвязать свое событие, вызвав возвращаемую функцию:

var myevent = $scope.$on('someEvents', handleSomeEvent);
myevent() ; // unbind the event

http://docs.angularjs.org/api/ng/function/angular.bind

Ответ 3

Как уже было сказано, Angular действительно позаботится о том, чтобы очищать вещи для вас, когда это возможно. Поэтому, если вы выполняете $scope.$on('someEvents', handleSomeEvent);, как только область будет уничтожена (например, когда вы переходите на другую страницу/просмотр в своем приложении), событие автоматически удаляется.

Важно отметить, что $rootScope, конечно, никогда не уничтожается, если вы не покинете свое приложение. Поэтому, если вы выполняете $rootScope.$on('someEvents', handleSomeEvent);, вам может потребоваться удалить событие самостоятельно, в зависимости от того, где вы слушаете событие:

  • если в controller или directive, вам придется удалить его вручную, иначе каждый раз, когда вы создадите экземпляр controller, будет добавлено новое событие, и поэтому handleSomeEvent будет много раз называется
  • если в service, вам не нужно удалять его вручную, так как службы всегда singleton (обратите внимание, что в Angular service, factory,... все в конечном итоге являются то же самое)