Auditeurs d'événements
Tout d'abord, il est important de comprendre qu'il existe deux types d '"écouteurs d'événements":
Auditeurs d'événements Scope enregistrés via $on
:
$scope.$on('anEvent', function (event, data) {
...
});
Les gestionnaires d'événements attachés aux éléments via par exemple on
ou bind
:
element.on('click', function (event) {
...
});
$ scope. $ destroy ()
Une fois $scope.$destroy()
exécuté, il supprimera tous les écouteurs enregistrés via $on
sur cette portée $.
Il ne supprimera pas les éléments DOM ou les gestionnaires d'événements attachés du deuxième type.
Cela signifie que l'appel $scope.$destroy()
manuel à partir d'un exemple dans la fonction de lien d'une directive ne supprimera pas un gestionnaire attaché via par exemple element.on
, ni l'élément DOM lui-même.
element.remove ()
Notez que remove
s'agit d'une méthode jqLite (ou d'une méthode jQuery si jQuery est chargé avant AngularjS) et n'est pas disponible sur un objet élément DOM standard.
Quand element.remove()
est exécuté cet élément et tous ses enfants seront supprimés du DOM ensemble tous les gestionnaires d'événements attachés via par exempleelement.on
.
Il ne détruira pas la portée $ associée à l'élément.
Pour le rendre plus déroutant, il existe également un événement jQuery appelé $destroy
. Parfois, lorsque vous travaillez avec des bibliothèques jQuery tierces qui suppriment des éléments, ou si vous les supprimez manuellement, vous devrez peut-être effectuer un nettoyage lorsque cela se produit:
element.on('$destroy', function () {
scope.$destroy();
});
Que faire lorsqu'une directive est "détruite"
Cela dépend de la façon dont la directive est "détruite".
Un cas normal est qu'une directive est détruite car elle ng-view
modifie la vue actuelle. Lorsque cela se produit, la ng-view
directive détruira la portée $ associée, coupera toutes les références à sa portée parent et appelleraremove()
l'élément.
Cela signifie que si cette vue contient une directive avec ceci dans sa fonction de lien lorsqu'elle est détruite par ng-view
:
scope.$on('anEvent', function () {
...
});
element.on('click', function () {
...
});
Les deux écouteurs d'événements seront supprimés automatiquement.
Cependant, il est important de noter que le code à l'intérieur de ces écouteurs peut toujours provoquer des fuites de mémoire, par exemple si vous avez atteint le modèle de fuite de mémoire JS commun circular references
.
Même dans ce cas normal où une directive est détruite en raison d'un changement de vue, vous devrez peut-être nettoyer manuellement certaines choses.
Par exemple, si vous avez enregistré un auditeur sur $rootScope
:
var unregisterFn = $rootScope.$on('anEvent', function () {});
scope.$on('$destroy', unregisterFn);
Cela est nécessaire car il $rootScope
n'est jamais détruit pendant la durée de vie de l'application.
Il en va de même si vous utilisez une autre implémentation pub / sub qui n'effectue pas automatiquement le nettoyage nécessaire lorsque la portée $ est détruite, ou si votre directive transmet des rappels aux services.
Une autre situation serait d'annuler $interval
/ $timeout
:
var promise = $interval(function () {}, 1000);
scope.$on('$destroy', function () {
$interval.cancel(promise);
});
Si votre directive associe des gestionnaires d'événements à des éléments, par exemple en dehors de la vue actuelle, vous devez également les nettoyer manuellement:
var windowClick = function () {
...
};
angular.element(window).on('click', windowClick);
scope.$on('$destroy', function () {
angular.element(window).off('click', windowClick);
});
Voici quelques exemples de ce qu'il faut faire lorsque des directives sont "détruites" par Angular, par exemple par ng-view
ou ng-if
.
Si vous avez des directives personnalisées qui gèrent le cycle de vie des éléments DOM, etc., cela deviendra bien sûr plus complexe.