Oyentes de eventos
En primer lugar, es importante comprender que hay dos tipos de "oyentes de eventos":
Oyentes de eventos de alcance registrados a través de $on
:
$scope.$on('anEvent', function (event, data) {
...
});
Controladores de eventos adjuntos a elementos mediante, por ejemplo, on
o bind
:
element.on('click', function (event) {
...
});
$ scope. $ destroy ()
Cuando $scope.$destroy()
se ejecute, eliminará todos los oyentes registrados a través $on
de ese $ scope.
Será no eliminar elementos DOM o cualquier controlador de eventos adjuntos de la segunda clase.
Esto significa que llamar $scope.$destroy()
manualmente desde el ejemplo dentro de la función de enlace de una directiva no eliminará un controlador adjunto a través de, por ejemplo element.on
, ni el elemento DOM en sí.
element.remove ()
Tenga en cuenta que remove
es un método jqLite (o un método jQuery si jQuery se carga antes que AngularjS) y no está disponible en un objeto de elemento DOM estándar.
Cuando element.remove()
se ejecuta ese elemento y todos sus elementos secundarios se eliminarán del DOM juntos, todos los controladores de eventos se adjuntarán a través de, por ejemplo element.on
.
Será no destruir el alcance $ asociado con el elemento.
Para hacerlo más confuso también hay un evento jQuery llamado $destroy
. A veces, cuando se trabaja con bibliotecas jQuery de terceros que eliminan elementos, o si las elimina manualmente, es posible que deba realizar una limpieza cuando eso suceda:
element.on('$destroy', function () {
scope.$destroy();
});
Qué hacer cuando una directiva es "destruida"
Esto depende de cómo se "destruye" la directiva.
Un caso normal es que una directiva se destruye porque ng-view
cambia la vista actual. Cuando esto suceda, la ng-view
directiva destruirá el $ alcance asociado, separe todas las referencias a su alcance principal y llame remove()
al elemento.
Esto significa que si esa vista contiene una directiva con esto en su función de enlace cuando es destruida por ng-view
:
scope.$on('anEvent', function () {
...
});
element.on('click', function () {
...
});
Ambos oyentes de eventos se eliminarán automáticamente.
Sin embargo, es importante tener en cuenta que el código dentro de estos oyentes aún puede causar pérdidas de memoria, por ejemplo, si ha logrado el patrón común de pérdida de memoria JS circular references
.
Incluso en este caso normal de una directiva que se destruye debido a un cambio de vista, hay cosas que puede necesitar limpiar manualmente.
Por ejemplo, si ha registrado un oyente en $rootScope
:
var unregisterFn = $rootScope.$on('anEvent', function () {});
scope.$on('$destroy', unregisterFn);
Esto es necesario ya $rootScope
que nunca se destruye durante la vida útil de la aplicación.
Lo mismo ocurre si está utilizando otra implementación de pub / sub que no realiza automáticamente la limpieza necesaria cuando se destruye el $ scope, o si su directiva transfiere devoluciones de llamada a los servicios.
Otra situación sería cancelar $interval
/ $timeout
:
var promise = $interval(function () {}, 1000);
scope.$on('$destroy', function () {
$interval.cancel(promise);
});
Si su directiva adjunta controladores de eventos a elementos, por ejemplo, fuera de la vista actual, también debe limpiarlos manualmente:
var windowClick = function () {
...
};
angular.element(window).on('click', windowClick);
scope.$on('$destroy', function () {
angular.element(window).off('click', windowClick);
});
Estos fueron algunos ejemplos de qué hacer cuando las directivas son "destruidas" por Angular, por ejemplo por ng-view
o ng-if
.
Si tiene directivas personalizadas que administran el ciclo de vida de los elementos DOM, etc., por supuesto, se volverá más complejo.
$rootScope
debido a esto: stackoverflow.com/questions/11252780/... Tenga en cuenta que, como la respuesta indica en la parte superior, esto ha cambiado. Sí, los oyentes de eventos normales$scope
se limpiarán automáticamente cuando se destruya ese alcance.