Ascoltatori di eventi
Prima di tutto è importante capire che esistono due tipi di "ascoltatori di eventi":
Ascoltatori di eventi Scope registrati tramite $on
:
$scope.$on('anEvent', function (event, data) {
...
});
Gestori di eventi collegati ad elementi tramite ad esempio on
o bind
:
element.on('click', function (event) {
...
});
$ Portata. $ Destroy ()
Quando $scope.$destroy()
viene eseguito rimuoverà tutti gli ascoltatori registrati tramite$on
quel $ scope.
Sarà Non rimuovere elementi DOM o qualsiasi gestori eventi allegati del secondo tipo.
Ciò significa che la chiamata $scope.$destroy()
manuale dall'esempio all'interno della funzione di collegamento di una direttiva non rimuoverà un gestore collegato tramite, ad esempio element.on
, né l'elemento DOM stesso.
element.remove ()
Nota che remove
è un metodo jqLite (o un metodo jQuery se jQuery è caricato prima di AngularjS) e non è disponibile su un oggetto elemento DOM standard.
Quando element.remove()
viene eseguito quell'elemento e tutti i suoi figli verranno rimossi dal DOM insieme, ad esempio, tutti i gestori di eventi collegati tramiteelement.on
.
Esso non distruggere il $ ambito associato all'elemento.
Per renderlo più confuso c'è anche un evento jQuery chiamato $destroy
. A volte, quando si lavora con librerie jQuery di terze parti che rimuovono elementi o se si rimuovono manualmente, potrebbe essere necessario eseguire la pulizia quando ciò accade:
element.on('$destroy', function () {
scope.$destroy();
});
Cosa fare quando una direttiva viene "distrutta"
Questo dipende da come la direttiva viene "distrutta".
Un caso normale è che una direttiva viene distrutta perché ng-view
cambia la vista corrente. Quando ciò accade, la ng-view
direttiva distrugge l'ambito $ associato, recide tutti i riferimenti al suo ambito padre e chiamaremove()
l'elemento.
Ciò significa che se quella vista contiene una direttiva con questa nella sua funzione di collegamento quando viene distrutta da ng-view
:
scope.$on('anEvent', function () {
...
});
element.on('click', function () {
...
});
Entrambi i listener di eventi verranno rimossi automaticamente.
Tuttavia, è importante notare che il codice all'interno di questi listener può comunque causare perdite di memoria, ad esempio se è stato raggiunto il modello di perdita di memoria JS comune circular references
.
Anche in questo caso normale in cui una direttiva viene distrutta a causa di una modifica della vista, è possibile che sia necessario ripulire manualmente.
Ad esempio se hai registrato un ascoltatore su $rootScope
:
var unregisterFn = $rootScope.$on('anEvent', function () {});
scope.$on('$destroy', unregisterFn);
Questo è necessario da allora $rootScope
non viene mai distrutto durante la vita dell'applicazione.
Lo stesso vale se si utilizza un'altra pub / sub implementazione che non esegue automaticamente la pulizia necessaria quando viene distrutto $ scope o se la direttiva trasmette i callback ai servizi.
Un'altra situazione sarebbe quella di annullare $interval
/ $timeout
:
var promise = $interval(function () {}, 1000);
scope.$on('$destroy', function () {
$interval.cancel(promise);
});
Se la direttiva collega gestori di eventi ad elementi esterni alla vista corrente, è necessario ripulire manualmente anche quelli:
var windowClick = function () {
...
};
angular.element(window).on('click', windowClick);
scope.$on('$destroy', function () {
angular.element(window).off('click', windowClick);
});
Questi sono stati alcuni esempi di cosa fare quando le direttive vengono "distrutte" da Angular, ad esempio da ng-view
o ng-if
.
Se hai direttive personalizzate che gestiscono il ciclo di vita degli elementi DOM ecc., Diventerà ovviamente più complesso.