ウォッチャーなしでコンポーネントを作成する
この回答では、ウォッチャーを使用せずに AngularJS 1.5 コンポーネントを作成するために使用する 5 つの手法について概説しています。
ng-change
ディレクティブを使用する
AngularJs2 の準備として watch を使用せずに obj の状態の変化を観察するために使用できる代替メソッドは何ですか?
ng-change
ディレクティブを使用して、入力の変更に対応できます。
<textarea ng-model='game.game'
ng-change="game.textChange(game.game)">
</textarea>
また、イベントを親コンポーネントに伝達するには、イベント ハンドラーを子コンポーネントの属性として追加する必要があります。
<game game='myBox.game' game-change='myBox.gameChange($value)'></game>
JS
app.component("game", {
bindings: {game:'=',
gameChange: '&'},
controller: function() {
var game = this;
game.textChange = function (value) {
game.gameChange({$value: value});
});
},
controllerAs: 'game',
templateUrl: "/template2"
});
そして、親コンポーネントで:
myBox.gameChange = function(newValue) {
console.log(newValue);
});
これは、今後推奨される方法です。使用する AngularJS 戦略$watch
は、ポーリング戦略であるため、スケーラブルではありません。リスナーの数が$watch
2000 前後になると、UI が遅くなります。Angular 2 の戦略は、フレームワークをより反応的にし、配置を避けること$watch
です$scope
。
$onChanges
ライフサイクル フックを使用する
バージョン 1.5.3で、AngularJS はサービスにライフサイクル フックを追加しまし$onChanges
た$compile
。
ドキュメントから:
コントローラーは、ライフサイクル フックとして機能する次のメソッドを提供できます。
- $onChanges(changesObj) - 一方向 (
<
) または補間 ( @
) バインディングが更新されるたびに呼び出されます。はchangesObj
、キーが変更されたバインドされたプロパティの名前であり、値が形式のオブジェクトであるハッシュです{ currentValue: ..., previousValue: ... }
。このフックを使用して、バインドされた値のクローンを作成するなど、コンポーネント内の更新をトリガーして、外部値の偶発的な変更を防ぎます。
— AngularJS Comprehensive Directive API Reference -- ライフサイクル フック
フックは、一方向バインディング$onChanges
でコンポーネントへの外部変更に対応するために使用されます。<
このng-change
ディレクティブは、コントローラーからの変更をバインディングを使用しng-model
てコンポーネントの外部に伝搬するために使用されます。&
$doCheck
ライフサイクル フックを使用する
バージョン 1.5.8で、AngularJS はサービスにライフサイクル フックを追加しまし$doCheck
た$compile
。
ドキュメントから:
コントローラーは、ライフサイクル フックとして機能する次のメソッドを提供できます。
$doCheck()
- ダイジェスト サイクルの各ターンで呼び出されます。変化を検出して対応する機会を提供します。検出した変更に応じて実行するアクションはすべて、このフックから呼び出す必要があります。これを実装しても、いつ$onChanges
呼び出されるかには影響しません。たとえば、このフックは、深い等価性チェックを実行したい場合や、Date オブジェクトをチェックしたい場合に役立ちます。これらの変更は、Angular の変更検出器によって検出されず、トリガーされません$onChanges
。このフックは引数なしで呼び出されます。変更を検出した場合は、現在の値と比較するために以前の値を保存する必要があります。
— AngularJS Comprehensive Directive API Reference -- ライフサイクル フック
とのコンポーネント間通信require
ディレクティブは、相互の通信を可能にするために、他のディレクティブのコントローラーを要求できます。これは、 requireプロパティにオブジェクト マッピングを提供することにより、コンポーネントで実現できます。オブジェクト キーは、必要なコントローラー (オブジェクト値) が必要なコンポーネントのコントローラーにバインドされるプロパティ名を指定します。
app.component('myPane', {
transclude: true,
require: {
tabsCtrl: '^myTabs'
},
bindings: {
title: '@'
},
controller: function() {
this.$onInit = function() {
this.tabsCtrl.addPane(this);
console.log(this);
};
},
templateUrl: 'my-pane.html'
});
詳細については、AngularJS 開発者ガイド - コンポーネント間通信を参照してください。
RxJSを使用してサービスから値をプッシュする
たとえば、状態を保持している Service がある状況ではどうでしょう。そのサービスに変更をプッシュし、ページ上の他のランダムなコンポーネントがそのような変更を認識できるようにするにはどうすればよいですか? 最近、この問題に取り組むのに苦労しています
RxJS Extensions for Angularを使用してサービスを構築します。
<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/rx/dist/rx.all.js"></script>
<script src="//unpkg.com/rx-angular/dist/rx.angular.js"></script>
var app = angular.module('myApp', ['rx']);
app.factory("DataService", function(rx) {
var subject = new rx.Subject();
var data = "Initial";
return {
set: function set(d){
data = d;
subject.onNext(d);
},
get: function get() {
return data;
},
subscribe: function (o) {
return subject.subscribe(o);
}
};
});
次に、変更を購読するだけです。
app.controller('displayCtrl', function(DataService) {
var $ctrl = this;
$ctrl.data = DataService.get();
var subscription = DataService.subscribe(function onNext(d) {
$ctrl.data = d;
});
this.$onDestroy = function() {
subscription.dispose();
};
});
クライアントは で変更をサブスクライブできDataService.subscribe
、プロデューサーは で変更をプッシュできますDataService.set
。
PLNKRのデモ。