Слушатели событий
Прежде всего, важно понимать, что существует два типа «слушателей событий»:
Слушатели событий Scope зарегистрированы через $on
:
$scope.$on('anEvent', function (event, data) {
...
});
Обработчики событий, прикрепленные к элементам, например, on
или bind
:
element.on('click', function (event) {
...
});
$ Сфера. $ Уничтожить ()
Когда $scope.$destroy()
выполняется, он удалит всех слушателей, зарегистрированных через $on
в этой области $.
Он не будет удалять элементы DOM или любые прикрепленные обработчики событий второго рода.
Это означает, что вызов $scope.$destroy()
вручную из примера в функции ссылки директивы не приведет к удалению обработчика, подключенного, например element.on
, через сам элемент DOM.
element.remove ()
Обратите внимание, что remove
это метод jqLite (или метод jQuery, если jQuery загружен до AngularjS) и недоступен в стандартном объектном элементе DOM.
Когда element.remove()
выполняется этот элемент и все его дочерние элементы будут удалены из DOM вместе, все обработчики событий будут присоединены, например, через element.on
.
Это не уничтожит область видимости $, связанную с элементом.
Чтобы сделать это еще более запутанным, существует также событие jQuery $destroy
. Иногда при работе со сторонними библиотеками jQuery, которые удаляют элементы, или если вы удаляете их вручную, вам может потребоваться выполнить очистку, когда это происходит:
element.on('$destroy', function () {
scope.$destroy();
});
Что делать, если директива «уничтожена»
Это зависит от того, как директива «уничтожена».
Обычным случаем является то, что директива уничтожается, потому что ng-view
изменяет текущее представление. Когда это произойдет, ng-view
директива уничтожит связанный $ scope, прервет все ссылки на родительскую область и вызовет remove()
элемент.
Это означает, что если это представление содержит директиву с этим в своей функции ссылки, когда оно уничтожено ng-view
:
scope.$on('anEvent', function () {
...
});
element.on('click', function () {
...
});
Оба слушателя событий будут удалены автоматически.
Тем не менее, важно отметить, что код внутри этих слушателей все еще может вызывать утечки памяти, например, если вы достигли общей схемы утечки памяти JS circular references
.
Даже в этом обычном случае, когда директива разрушается из-за смены представления, есть вещи, которые вам, возможно, придется очистить вручную.
Например, если вы зарегистрировали слушателя на $rootScope
:
var unregisterFn = $rootScope.$on('anEvent', function () {});
scope.$on('$destroy', unregisterFn);
Это необходимо, так $rootScope
как никогда не уничтожается в течение времени жизни приложения.
То же самое происходит, если вы используете другую реализацию pub / sub, которая автоматически не выполняет необходимую очистку при уничтожении $ scope или если ваша директива передает обратные вызовы сервисам.
Другая ситуация будет отменить $interval
/ $timeout
:
var promise = $interval(function () {}, 1000);
scope.$on('$destroy', function () {
$interval.cancel(promise);
});
Если ваша директива присоединяет обработчики событий к элементам, например, вне текущего представления, вам также необходимо вручную их очистить:
var windowClick = function () {
...
};
angular.element(window).on('click', windowClick);
scope.$on('$destroy', function () {
angular.element(window).off('click', windowClick);
});
Это были некоторые примеры того, что делать, когда директивы «уничтожаются» Angular, например, ng-view
или ng-if
.
Если у вас есть пользовательские директивы, управляющие жизненным циклом элементов DOM и т. Д., Это, конечно, станет более сложным.