チーム開発のための太字のAngularJSスタイルガイド[2/2]

翻訳の最初の部分はこちらです。

GoogleのAngularJSガイドラインを読んだ後、その不完全さの印象を受け、その中でClosureライブラリを使用することの利益をしばしば示唆しました。 また 、「これらの推奨事項が、AngularJSを使用するすべてのプロジェクトに等しく適用できるとは考えていません。 小規模プロジェクトと大規模プロジェクトの両方に適用できる、より一般的なスタイルガイドのコミュニティからのイニシアチブをご覧いただければ幸いです。」

Angularでの個人的な経験、 いくつかのスピーチ 、およびチーム開発の経験に基づいて、AngularJSのアプリケーションの構文、コーディング、および構造に関するこの大胆なスタイルガイドを紹介します。

指令


DOMを使用したすべての操作は、ディレクティブからのみ行う必要があります。 再利用に適したコードはすべてカプセル化する必要があります(これはアクションとマークアップにも適用されます)。

DOM操作


DOMを使用した操作は、ディレクティブのlinkメソッドで行う必要があります。

悪い:

 //    function MainCtrl (SomeService) { this.makeActive = function (elem) { elem.addClass('test'); }; } angular .module('app') .controller('MainCtrl', MainCtrl); 

良い:

 //   function SomeDirective (SomeService) { return { restrict: 'EA', template: [ '<a href="" class="myawesomebutton" ng-transclude>', '<i class="icon-ok-sign"></i>', '</a>' ].join(''), link: function ($scope, $element, $attrs) { // DOM manipulation/events here! $element.on('click', function () { $(this).addClass('test'); }); } }; } angular .module('app') .directive('SomeDirective', SomeDirective); 

命名規則


Angularの将来のリリースによるコードの再割り当ての可能性を避けるために、カスタムディレクティブの名前にng-*プレフィックスをng-*ないでください。 確かに、 ng-focus登場した時点で、多くのディレクティブは同じ名前で記述されていましたが、アプリケーションでの作業は同じ名前を使用したために麻痺していました。 また、このプレフィックスの使用は混乱を招き、外部からは、どのディレクティブがユーザーによって記述され、どのディレクティブがライブラリに付属しているかはビューコードから明確ではありません。

悪い:

 function ngFocus (SomeService) { return {}; } angular .module('app') .directive('ngFocus', ngFocus); 

良い:

 function focusFire (SomeService) { return {}; } angular .module('app') .directive('focusFire', focusFire); 

CamelCaseは、ディレクティブに名前を付けるために使用されます。 ディレクティブの名前の最初の文字は小文字です。 ビューコードでは、既にハイフンで記述されたディレクティブの名前を使用していることにも注意してください。 したがって、ビューでfocusFireディレクティブを使用するには、 <input focus-fire>介してfocusFire

使用制限


IE8のサポートが重要な場合、ディレクティブではコメント付きの構文を使用する必要があります。 実際、この形式のディレクティブ呼び出しを使用する理由は他にありません。 可能であれば、この構文でも使用しないほうがよいでしょう。実際のコメントの場所とディレクティブの呼び出し場所が混乱する可能性があるためです。

悪い:

これは非常に紛らわしいです。

 <!-- directive: my-directive --> <div class="my-directive"></div> 

良い:

宣言的なユーザーディレクティブはより表情豊かに見えます。

 <my-directive></my-directive> <div my-directive></div> 

ルーターで解決を約束し、コントローラーで延期する


サービスを作成した後、おそらくデータで作業するためにコントローラーでそれらを使用したいと思うでしょう。 したがって、時間の経過とともに、適切なデータを取得するとともに、コントローラーの見た目をきれいに保つことが問題になる可能性があります。

angular-route.js (またはui-router.jsなどの同様のサードパーティアドオン)のui-router.jsresolveプロパティを使用して、完成したページが表示されるまで次のビューの約束を解決resolve機会が得られます。 これは、このビューのコントローラーがすべてのデータを受信した直後に作成されることを意味し、これは今度はこの時点まで関数呼び出しが行われないことを意味します。

悪い:

 function MainCtrl (SomeService) { var self = this; //    self.something; //    SomeService.doSomething().then(function (response) { self.something = response; }); } angular .module('app') .controller('MainCtrl', MainCtrl); 

良い:

 function config ($routeProvider) { $routeProvider .when('/', { templateUrl: 'views/main.html', resolve: { doSomething: function (SomeService) { return SomeService.doSomething(); } } }); } angular .module('app') .config(config); 

この段階では、サービス内で、Promiseは別のオブジェクトにバインドされ、「遅延」コントローラーに転送できます。

良い:

 function MainCtrl (SomeService) { //  ! this.something = SomeService.something; } angular .module('app') .controller('MainCtrl', MainCtrl); 

しかし、改善できるものがまだあります。 resolveプロパティをコントローラーコードに直接転送できます。これにより、ルーターコードにロジックが存在することを回避できます。

素晴らしい:

 // ,  resolve       function config ($routeProvider) { $routeProvider .when('/', { templateUrl: 'views/main.html', controller: 'MainCtrl', controllerAs: 'main', resolve: MainCtrl.resolve }); } // ,  function MainCtrl (SomeService) { //  ! this.something = SomeService.something; } //   resolve    MainCtrl.resolve = { doSomething: function (SomeService) { return SomeService.doSomething(); } }; angular .module('app') .controller('MainCtrl', MainCtrl) .config(config); 

ルートとスピナーの変更


新しいルートを解決するプロセスでは、進行状況を示す何かを表示したいと思うでしょう。 いつものように、Angular $routeChangeStart現在のページを離れるときに$routeChangeStartイベントを発生させます。 この瞬間、スピナーを見せることができます。 また、 $routeChangeSuccessイベント$routeChangeSuccessしたときに削除でき$routeChangeSuccess詳細はこちら )。

$スコープを避けます。


$scope.$watch使用します$scope.$watchそれなしで実行する方法がない場合にのみ$scope.$watchします。 パフォーマンスにおいて、 ng-changeソリューションよりも著しく劣ることを覚えておく価値があります。

悪い:

 <input ng-model="myModel"> <script> $scope.$watch('myModel', callback); </script> 

良い:

 <input ng-model="myModel" ng-change="callback"> <!-- $scope.callback = function () { // go }; --> 

プロジェクト構造


各コントローラー、サービス、またはディレクティブは、個別のファイルに配置する必要があります。 すべてのコントローラーを1つのファイルにプッシュしないでください。将来的にそこに何かを見つけるのが非常に困難になるという理由だけのためです。
悪い:

 |-- app.js |-- controllers.js |-- filters.js |-- services.js |-- directives.js 

良い:

その内容のみが名前から始まるように最大限に理解するために、容量の大きい話し言葉のファイル名に固執します。

 |-- app.js |-- controllers/ | |-- MainCtrl.js | |-- AnotherCtrl.js |-- filters/ | |-- MainFilter.js | |-- AnotherFilter.js |-- services/ | |-- MainService.js | |-- AnotherService.js |-- directives/ | |-- MainDirective.js | |-- AnotherDirective.js 

プロジェクトのコードベースのサイズに応じて、ファイルの命名に対する機能的なアプローチがより適している場合があります。

良い:

 |-- app.js |-- dashboard/ | |-- DashboardService.js | |-- DashboardCtrl.js |-- login/ | |-- LoginService.js | |-- LoginCtrl.js |-- inbox/ | |-- InboxService.js | |-- InboxCtrl.js 

命名規則と競合


Angularには、 $scope$rootScopeなど、名前が$記号で始まるオブジェクトが多数あります。 このシンボルは、いわば、このオブジェクトまたはそのオブジェクトがパブリックであり、さまざまな場所から操作できることを示唆しています。 また、 $$listenersようなものにも精通してい$$listeners 。これらはコードでも利用できますが、プライベートと見なされます。

上記のすべては、独自のディレクティブ/サービス/コントローラー/プロバイダー/ファクトリーの名前に接頭辞として$$$を使用することを避けるべきだと言っているだけです。

悪い:

ここでは、 $$SomeServiceとして関数名を残したまま、 $$SomeServiceを定義として設定します。

 function SomeService () { } angular .module('app') .factory('$$SomeService', SomeService); 

良い:

ここでは、より表現力豊かなスタックトレースのために、 SomeServiceを関数自体の定義名前として定義ます。

 function SomeService () { } angular .module('app') .factory('SomeService', SomeService); 

縮小と注釈


注釈の順序


モジュールの依存関係のリストに最初にAngularプロバイダーをリストし、その後、独自のものをリストすることをお勧めします。

悪い:

 //    function SomeCtrl (MyService, $scope, AnotherService, $rootScope) { } 

良い:

 //   Angular ->  function SomeCtrl ($scope, $rootScope, MyService, AnotherService) { } 

縮小を自動化する


ng-min 廃止され、サポートされなくなったためng-annotateを使用して依存関係に自動的に注釈を付けます。 ng-annotateについては、 ここで詳しく説明します

私たちの場合、モジュールコードを別の関数で記述する場合、適切に縮小するには、依存関係のある関数の前に@ngInjectコメントを使用する必要があります。 このコメントは、モジュールの依存関係を自動的に記述するng-annotate命令です。

悪い:

 function SomeService ($scope) { } //    –     SomeService.$inject = ['$scope']; angular .module('app') .factory('SomeService', SomeService); 

良い:

 /** * @ngInject */ function SomeService ($scope) { } angular .module('app') .factory('SomeService', SomeService); 

その結果、これは次のようになります。

 /** * @ngInject */ function SomeService ($scope) { } //   ng-annotate   SomeService.$inject = ['$scope']; angular .module('app') .factory('SomeService', SomeService); 

このスタイルガイドは、最終段階にあります。 常に最新の推奨事項がGithubにあります。

Source: https://habr.com/ru/post/J237279/


All Articles