[解決済み】AngularJS - $destroyは、イベントリスナーを削除しますか?
質問
https://docs.angularjs.org/guide/directive
このイベントをリッスンすることで、メモリリークの原因となりうるイベントリスナーを削除することができます。スコープや要素に登録したリスナーは破棄される際に自動的にクリーンアップされますが、サービスにリスナーを登録した場合や、削除されないDOMノードにリスナーを登録した場合は、自分でクリーンアップしなければメモリリークを引き起こす危険性があります。
ベストプラクティス。ディレクティブは自分自身で後始末をする必要があります。element.on('$destroy', ...) や scope.$on('$destroy', ...) を使って、ディレクティブが削除されたときにクリーンアップ関数を実行させることができます。
質問です。
私は
element.on "click", (event) ->
をディレクティブの中に入れてください。
-
ディレクティブが破棄されたとき、そのディレクティブの中に
element.on
ガベージコレクションされないようにするため? -
Angularのドキュメントによると、イベントリスナーを削除するためにハンドラを使用する必要があります。
$destroy
が発行されました。という印象を持ちました。destroy()
はイベントリスナーを削除していますが、そうではないのでしょうか?
解決方法は?
イベントリスナー
まず最初に、イベントリスナーには2つの種類があることを理解しておくことが重要です。
-
で登録したスコープイベントリスナー。
$on
:$scope.$on('anEvent', function (event, data) { ... });
-
イベントハンドラは、例えば、以下のような方法で要素にアタッチされます。
on
またはbind
:element.on('click', function (event) { ... });
スコープ.$destroy()
いつ
$scope.$destroy()
を介して登録されたリスナーはすべて削除されます。
$on
をその$scopeで使用します。
それは ない は、DOM要素や付属のイベントハンドラ(2種類目)を削除します。
つまり
$scope.$destroy()
ディレクティブのリンク関数の中で、たとえば
element.on
また、DOM 要素自体も同様です。
要素.remove()
なお
remove
は jqLite のメソッド(jQuery が AngularjS よりも先にロードされている場合は jQuery のメソッド)であり、標準の DOM Element Object では使用できない。
いつ
element.remove()
が実行されると、その要素とすべての子要素が DOM から削除され、たとえば
element.on
.
それは ない 要素に関連付けられた $scope を破棄します。
さらに分かりやすくするために、jQueryのイベントとして
$destroy
. 要素を削除するサードパーティのjQueryライブラリを使用する場合、または手動で削除する場合、その際にクリーンアップを実行する必要があることがあります。
element.on('$destroy', function () {
scope.$destroy();
});
ディレクティブが破壊されたときの対処方法。
これは、ディレクティブがどのように破壊されるかによります。
通常の場合、ディレクティブが破壊されるのは
ng-view
は現在のビューを変更します。このような場合
ng-view
ディレクティブは関連する $scope を破棄し、 その親スコープへの参照をすべて破棄して
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要素のライフサイクルを管理するカスタムディレクティブなどがある場合は、もちろんもっと複雑になります。
関連
-
[解決済み] ページロード時にAngularJSのコントローラ関数を実行する方法は?
-
[解決済み] Angular ng-repeat エラー "リピータ内の重複は許可されません。"
-
[解決済み] AngularJSのng-showとフェードアニメーション
-
[解決済み] AngularJsでng-Cloakディレクティブを実際に使用する方法とは?
-
[解決済み] AngularJSでデータバインディングはどのように機能するのですか?
-
[解決済み] AngularJSを使用して、ブラウザのコンソールで$scope変数にアクセスするにはどうすればよいですか?
-
[解決済み] AngularJSで$scope.$watchと$scope.$applyを使用するにはどうすればよいですか?
-
[解決済み] AngularJS コントローラにおける 'this' と $scope の比較
-
[解決済み] ServiceとFactoryで迷う
-
[解決済み] 条件に応じて特定のルートにリダイレクトする機能
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] ReferenceError: Angularは定義されていません。
-
[解決済み] AngularJsでng-Cloakディレクティブを実際に使用する方法とは?
-
angularjs統合ueditor入門
-
angularjsのルーティングについて $stateと$stateParamsの話
-
[解決済み] AngularJSとHandlebars - 両方必要なのかどうか
-
[解決済み] ServiceとFactoryで迷う
-
[解決済み] AngularJSでコントローラを2回実行する場合の対処法
-
[解決済み] AngularJSでコントローラ間の通信を行う正しい方法は何ですか?
-
[解決済み] ng-repeat内のng-click関数にパラメータを追加しても、うまくいかないようです。
-
[解決済み] AngularJSでEnterキーを押したときにフォームを送信する