Ouvintes de eventos
Primeiro, é importante entender que existem dois tipos de "ouvintes de eventos":
Ouvintes de eventos de escopo registrados via $on:
$scope.$on('anEvent', function (event, data) {
...
});
Manipuladores de eventos anexados a elementos via, por exemplo, onou bind:
element.on('click', function (event) {
...
});
$ scope. $ destroy ()
Quando $scope.$destroy()é executado, ele remove todos os ouvintes registrados $onnesse escopo $.
Ele não removerá elementos DOM ou qualquer manipulador de eventos anexado do segundo tipo.
Isso significa que a chamada $scope.$destroy()manual do exemplo na função de link de uma diretiva não removerá um manipulador anexado por exemplo element.on, nem o próprio elemento DOM.
element.remove ()
Observe que removeé um método jqLite (ou um método jQuery se o jQuery for carregado antes do AngularjS) e não estiver disponível em um Objeto de Elemento DOM padrão.
Quando element.remove()é executado, esse elemento e todos os seus filhos serão removidos do DOM juntos, todos os manipuladores de eventos anexados via, por exemplo element.on.
Ele vai não destruir a $ âmbito associado ao elemento.
Para torná-lo mais confuso, também há um evento jQuery chamado $destroy. Às vezes, ao trabalhar com bibliotecas jQuery de terceiros que removem elementos ou se você os remove manualmente, pode ser necessário executar uma limpeza quando isso acontece:
element.on('$destroy', function () {
scope.$destroy();
});
O que fazer quando uma diretiva é "destruída"
Isso depende de como a diretiva é "destruída".
Um caso normal é que uma diretiva é destruída porque ng-viewaltera a exibição atual. Quando isso acontece, a ng-viewdiretiva destrói o escopo $ associado, interrompe todas as referências ao escopo pai e invoca remove()o elemento.
Isso significa que, se essa exibição contiver uma diretiva com isso em sua função de link, quando for destruída por ng-view:
scope.$on('anEvent', function () {
...
});
element.on('click', function () {
...
});
Os dois ouvintes de eventos serão removidos automaticamente.
No entanto, é importante observar que o código dentro desses ouvintes ainda pode causar vazamentos de memória, por exemplo, se você atingiu o padrão de vazamento de memória JS comum circular references.
Mesmo nesse caso normal de uma diretiva ser destruída devido a uma alteração na exibição, há coisas que você pode precisar limpar manualmente.
Por exemplo, se você registrou um ouvinte em $rootScope:
var unregisterFn = $rootScope.$on('anEvent', function () {});
scope.$on('$destroy', unregisterFn);
Isso é necessário, pois $rootScopenunca é destruído durante a vida útil do aplicativo.
O mesmo acontece se você estiver usando outra implementação de publicação / publicação que não executa automaticamente a limpeza necessária quando o escopo $ é destruído ou se sua diretiva passa retornos de chamada para serviços.
Outra situação seria cancelar $interval/ $timeout:
var promise = $interval(function () {}, 1000);
scope.$on('$destroy', function () {
$interval.cancel(promise);
});
Se sua diretiva anexar manipuladores de eventos a elementos, por exemplo, fora da visualização atual, você também precisará limpá-los manualmente:
var windowClick = function () {
...
};
angular.element(window).on('click', windowClick);
scope.$on('$destroy', function () {
angular.element(window).off('click', windowClick);
});
Estes foram alguns exemplos do que fazer quando as diretivas são "destruídas" pelo Angular, por exemplo, por ng-viewou ng-if.
Se você possui diretivas personalizadas que gerenciam o ciclo de vida dos elementos DOM, etc., é claro que ficará mais complexo.