Слухачі подій
По-перше, важливо зрозуміти, що існує два види "слухачів подій":
Слухачі події сфери застосування зареєстровані через $on
:
$scope.$on('anEvent', function (event, data) {
...
});
Обробники подій, приєднані до елементів за допомогою, наприклад, on
або bind
:
element.on('click', function (event) {
...
});
$ область. $ знищити ()
Коли $scope.$destroy()
це буде виконано, він видалить усіх слухачів, зареєстрованих через $on
цю область $.
Він не буде видаляти елементи DOM або будь-які додані обробники подій другого роду.
Це означає, що виклик $scope.$destroy()
вручну з прикладу в межах функції посилання директиви не буде видаляти обробник, приєднаний, наприклад element.on
, ні сам елемент DOM.
element.remove ()
Зауважте, що remove
це метод jqLite (або метод jQuery, якщо jQuery завантажується перед AngularjS) і недоступний у стандартному об'єкті елемента DOM.
Після element.remove()
виконання цього елемента і всі його діти будуть видалені з DOM разом, наприклад, всі обробники подій, додані, наприклад, через element.on
.
Це не зруйнує область $, пов'язану з елементом.
Щоб зробити його більш заплутаним, існує також подія jQuery $destroy
. Іноді під час роботи зі сторонніми бібліотеками jQuery, які видаляють елементи, або якщо ви видаляєте їх вручну, можливо, знадобиться виконати очищення, коли це станеться:
element.on('$destroy', function () {
scope.$destroy();
});
Що робити, коли директива "знищена"
Це залежить від того, як директива "знищується".
Нормальним є те, що директива руйнується через те, що ng-view
змінюється поточний погляд. Коли це станеться, ng-view
директива знищить пов'язаний $ range, розділить усі посилання на його батьківський обсяг та викличеremove()
елемент.
Це означає, що якщо цей погляд містить директиву з цим у своїй функції зв’язку, коли він знищений ng-view
:
scope.$on('anEvent', function () {
...
});
element.on('click', function () {
...
});
Обидва слухачі подій будуть видалені автоматично.
Однак важливо зауважити, що код всередині цих слухачів все ще може спричинити витік пам'яті, наприклад, якщо ви досягли загальної схеми витоку пам'яті JS circular references
.
Навіть у цьому звичайному випадку руйнування директиви через зміну перегляду є речі, які можуть знадобитися вручну очистити.
Наприклад, якщо ви зареєстрували слухача на $rootScope
:
var unregisterFn = $rootScope.$on('anEvent', function () {});
scope.$on('$destroy', unregisterFn);
Це потрібно з тих пір $rootScope
ніколи не руйнується протягом життя програми.
Те ж саме, якщо ви використовуєте іншу реалізацію pub / sub, яка автоматично не виконує необхідну очистку при знищенні діапазону $ або якщо ваша директива передає зворотні виклики службам.
Іншою ситуацією було б скасування $interval
/ $timeout
:
var promise = $interval(function () {}, 1000);
scope.$on('$destroy', function () {
$interval.cancel(promise);
});
Якщо ваша директива приєднує обробники подій до елементів, наприклад, поза поточним поданням, вам також потрібно вручну очистити їх:
var windowClick = function () {
...
};
angular.element(window).on('click', windowClick);
scope.$on('$destroy', function () {
angular.element(window).off('click', windowClick);
});
Це були деякі приклади того, що робити, коли директиви "зруйновані" Angular, наприклад, ng-view
або ng-if
.
Якщо у вас є власні директиви, що керують життєвим циклом елементів DOM тощо, звичайно, це стане складніше.