Detektory zdarzeń
Po pierwsze, ważne jest, aby zrozumieć, że istnieją dwa rodzaje „detektorów zdarzeń”:
Zakres detektorów zdarzeń zarejestrowanych za pośrednictwem $on
:
$scope.$on('anEvent', function (event, data) {
...
});
Procedury obsługi zdarzeń dołączone do elementów na przykład on
lub bind
:
element.on('click', function (event) {
...
});
$ scope. $ destroy ()
Po $scope.$destroy()
wykonaniu usunie wszystkich słuchaczy zarejestrowanych za pośrednictwem $on
tego zakresu $.
To będzie nie usuwać elementów DOM i wszystkie podłączone obsługi zdarzeń drugiego rodzaju.
Oznacza to, że $scope.$destroy()
ręczne wywołanie z przykładu w ramach funkcji link dyrektywy nie usunie element.on
modułu obsługi dołączonego na przykład ani samego elementu DOM.
element.remove ()
Zauważ, że remove
jest to metoda jqLite (lub metoda jQuery, jeśli jQuery jest ładowane przed AngularjS) i nie jest dostępna w standardowym obiekcie elementu DOM.
Kiedy element.remove()
zostanie wykonany, ten element i wszystkie jego elementy potomne zostaną razem usunięte z DOM, a wszystkie procedury obsługi zdarzeń zostaną podłączone na przykład za pośrednictwem element.on
.
To będzie nie zniszczyć zakresu $ powiązany z elementem.
Aby było bardziej mylące, istnieje również zdarzenie jQuery $destroy
. Czasami podczas pracy z bibliotekami jQuery innych firm, które usuwają elementy, lub jeśli usuwasz je ręcznie, może być konieczne wykonanie czyszczenia, gdy tak się stanie:
element.on('$destroy', function () {
scope.$destroy();
});
Co zrobić, gdy dyrektywa zostaje „zniszczona”
Zależy to od „zniszczenia” dyrektywy.
Normalnym przypadkiem jest zniszczenie dyrektywy, ponieważ ng-view
zmienia ona obecny widok. Kiedy tak się stanie, ng-view
dyrektywa zniszczy powiązany zakres $, zerwie wszystkie odniesienia do zakresu nadrzędnego i wywołanie remove()
elementu.
Oznacza to, że jeśli ten widok zawiera dyrektywę z tą funkcją w funkcji link, gdy zostanie zniszczony przez ng-view
:
scope.$on('anEvent', function () {
...
});
element.on('click', function () {
...
});
Oba detektory zdarzeń zostaną automatycznie usunięte.
Należy jednak pamiętać, że kod wewnątrz tych detektorów może nadal powodować wycieki pamięci, na przykład jeśli osiągnąłeś wspólny wzór wycieku pamięci JS circular references
.
Nawet w tym normalnym przypadku zniszczenia dyrektywy z powodu zmiany widoku istnieją rzeczy, które mogą być potrzebne do ręcznego wyczyszczenia.
Na przykład, jeśli zarejestrowałeś nasłuchującego na $rootScope
:
var unregisterFn = $rootScope.$on('anEvent', function () {});
scope.$on('$destroy', unregisterFn);
Jest to potrzebne od tego czasu $rootScope
nigdy nie jest niszczone w trakcie życia aplikacji.
To samo dotyczy sytuacji, gdy używasz innej implementacji pub / sub, która nie wykonuje automatycznie koniecznego czyszczenia po zniszczeniu zakresu $ lub jeśli twoja dyrektywa przekazuje wywołania zwrotne do usług.
Inną sytuacją byłoby anulowanie $interval
/ $timeout
:
var promise = $interval(function () {}, 1000);
scope.$on('$destroy', function () {
$interval.cancel(promise);
});
Jeśli twoja dyrektywa dołącza procedury obsługi zdarzeń do elementów, na przykład poza bieżącym widokiem, musisz je również ręcznie wyczyścić:
var windowClick = function () {
...
};
angular.element(window).on('click', windowClick);
scope.$on('$destroy', function () {
angular.element(window).off('click', windowClick);
});
Oto kilka przykładów tego, co zrobić, gdy dyrektywy zostaną „zniszczone” przez Angulara, na przykład przez ng-view
lub ng-if
.
Jeśli masz niestandardowe dyrektywy, które zarządzają cyklem życia elementów DOM itp., Będzie to oczywiście bardziej skomplikowane.
$rootScope
z tego powodu skorzystać : stackoverflow.com/questions/11252780/... Pamiętaj, że ponieważ odpowiedź u góry jest zmieniona. Tak, nasłuchiwanie zdarzeń normalnie$scope
zostanie automatycznie wyczyszczone, gdy ten zakres zostanie zniszczony.