どちらが優れていると考えられますか:
- サービスと直接やり取りするディレクティブを持つ
または
- コントローラが動作をバインドする特定のフックを公開するディレクティブを持っていますか?
どちらが優れていると考えられますか:
または
回答:
ディレクティブは(経験則として)短く(コード単位で)、(潜在的に)再利用可能であり、機能の面で範囲が限られている場合に最適です。UIを含み、サービスに依存するディレクティブ(バックエンドへの接続を処理することを前提とする)を作成し、2つの機能的な役割を与えるだけではありません。
また、別のサービスや別のUIで(少なくとも簡単に)使用できないため、再利用しにくくします。
これらの決定をするとき、私はしばしば組み込みのHTML要素と比較します:例えば<input>
、<textarea>
または<form>
:それらは特定のバックエンドから完全に独立しています。HTML5は、<input>
要素にいくつかの追加の型を与えました。たとえばdate
、まだバックエンドから独立しており、データがどこに行くか、どのように使用されるかです。これらは純粋にインターフェース要素です。ディレクティブを使用して構築されたカスタムウィジェットは、可能であれば同じパターンに従う必要があると思います。
ただし、これで話は終わりではありません。組み込みのHTML要素との類似性を超えて、サービスを呼び出す再利用可能なディレクティブを作成し、純粋にUIディレクティブを使用できます<textarea>
。次のようにHTMLを使用するとします。
<document document-url="'documents/3345.html'">
<document-data></document-data>
<comments></comments>
<comment-entry></comment-entry>
</document>
commentEntry
ディレクティブをコーディングするには、UIウィジェットとサービスをリンクするコントローラーのみを含む非常に小さなディレクティブを作成できます。何かのようなもの:
app.directive('commentEntry', function (myService) {
return {
restrict: 'E',
template: '<comment-widget on-save="save(data)" on-cancel="cancel()"></comment-widget>',
require: '^document',
link: function (scope, iElement, iAttrs, documentController) {
// Allow the controller here to access the document controller
scope.documentController = documentController;
},
controller: function ($scope) {
$scope.save = function (data) {
// Assuming the document controller exposes a function "getUrl"
var url = $scope.documentController.getUrl();
myService.saveComments(url, data).then(function (result) {
// Do something
});
};
}
};
});
これを極端にするng-controller
と、HTMLに手動の属性を持つ必要はないかもしれません。それぞれが明確な「UI」ロールまたは明確な「データ」ロールを持っている限り、ディレクティブを使用してすべて行うことができます。
私が言及しなければならない欠点があります:それは、アプリケーションにより多くの「可動部分」を与え、それは少し複雑さを追加します。ただし、各部分に明確な役割があり、うまく機能している場合(ユニット+ E2Eテスト済み)、それは価値があり、長期的には全体的な利点があると主張します。
Michal Charemzaの答えに反対させてください。
彼の答えは理論的には正しいが、現実の世界ではあまり実用的ではない。
私はそのように考えていたので、自分と私のチームが構築している大規模な現実世界のアプリでそれを強制しようとしたので、それが面倒になりすぎたと言っています。
HTML言語との類似性は良くありません。なぜなら、Webブラウザーのような一般的なアプリケーションを構築しているわけではないので、汎用で非常に再利用可能なディレクティブを構築しようと努力すべきではないからです。
代わりに、ディレクティブを使用して、独自のドメインに存在するアプリのドメイン固有言語(DSL)を構築する必要があります。
それは、すべてのディレクティブがジェネリックであってはならないという意味ではありません。それが彼らの性質にあるならば、いくつかはそうかもしれません。カスタムの日付ピッカーを作成している場合は、すべてのアプリで一般的に再利用できるようにします。
ただし、バックエンドにバインドするログインボックスのようなものを作成する場合は、それを実行してください。
唯一の経験則は次のとおりです。コード(工場やサービスの一部を抽象化しない)を決して複製せず、依存性注入によってテスト可能にします。幸いなことに、Angularでは、これらは非常に簡単です。
複雑にしないでおく。:)
「ディレクティブがサービスと対話する必要がある」という質問は、サービスの実行内容に依存すると思います。
HTTPリクエストに対して何もしないサービスと対話するディレクティブがありますが、これは良いパターンだと思います。サービス/ファクトリーは、より多くのデータ指向のロジックをカプセル化するのに最適であり、ディレクティブはプレゼンテーション指向のロジックをカプセル化するのに最適です。Angularドキュメントに記載されているサービスの目的は次のとおりです。「サービスを使用して、アプリ全体でコードを整理および共有できます。」それはかなり広範ですが、ディレクティブを使用してその目標を達成するためにサービスを使用できます。
そうは言っても、ディレクティブがHTTPリクエストを直接行わないようにしたい場合があることを理解しています。繰り返しますが、それはサービスとサービスの構成方法に依存します。