Modül bildirimi için en iyi AngularJS uygulamaları?


115

Uygulamamda bir dizi Açısal modül beyan ettim. Başlangıçta bunları "zincirleme" sözdizimini kullanarak şu şekilde açıklamaya başladım:

angular.module('mymodule', [])
    .controller('myctrl', ['dep1', function(dep1){ ... }])
    .service('myservice', ['dep2', function(dep2){ ... }])
    ... // more here

Ama okumanın çok kolay olmadığına karar verdim, bu yüzden onları şöyle bir modül değişkeni kullanarak ilan etmeye başladım:

var mod = angular.module('mymodule', []);

mod.controller('myctrl', ['dep1', function(dep1){ ... }]);

mod.service('myservice', ['dep2', function(dep2){ ... }]);
...

İkinci sözdizimi bana çok daha okunabilir görünüyor, ancak tek şikayetim, bu sözdiziminin moddeğişkeni genel kapsamda bırakmasıdır. Eğer isimlendirilmiş başka bir değişkenim modolursa, bu bir sonraki değişkenle (ve genel değişkenlerle ilişkili diğer sorunlar) geçersiz kılınır.

Yani sorum şu, bu en iyi yol mu? Yoksa böyle bir şey yapmak daha mı iyi olur ?:

(function(){
    var mod = angular.module('mymod', []);
    mod.controller('myctrl', ['dep1', function(dep1){ ... }]);
    mod.service('myservice', ['dep2', function(dep2){ ... }]);
    ...
})();

Ya da umursayacak kadar önemli mi? Modül bildirimi için "en iyi uygulamaların" ne olduğunu merak ediyorum. Şimdiden teşekkürler.


Yanıtlar:


118

Bir modül bildirmenin 'en iyi' yolu

Açısal, genel kapsamın kendisinde olduğundan ve modüller değişkenine kaydedildiğinden, modüllere şu yolla erişebilirsiniz angular.module('mymod'):

// one file
// NOTE: the immediately invoked function expression 
// is used to exemplify different files and is not required
(function(){
   // declaring the module in one file / anonymous function
   // (only pass a second parameter THIS ONE TIME as a redecleration creates bugs
   // which are very hard to dedect)
   angular.module('mymod', []);
})();


// another file and/or another anonymous function
(function(){   
 // using the function form of use-strict...
 "use strict";
  // accessing the module in another. 
  // this can be done by calling angular.module without the []-brackets
  angular.module('mymod')
    .controller('myctrl', ['dep1', function(dep1){
      //..
    }])

  // appending another service/controller/filter etc to the same module-call inside the same file
    .service('myservice', ['dep2', function(dep2){ 
    //... 
    }]);

  // you can of course use angular.module('mymod') here as well
  angular.module('mymod').controller('anothermyctrl', ['dep1', function(dep1){
      //..
  }])
})();

Başka genel değişkenlere gerek yoktur.

Elbette hepsi tercihlere bağlıdır, ancak bunun en iyi uygulama olduğunu düşünüyorum.

  1. küresel kapsamı kirletmek zorunda değilsin
  2. modüllerinize her yerden erişebilir ve bunları ve işlevlerini istediğiniz zaman farklı dosyalara sıralayabilirsiniz
  3. "sıkı kullan" işlev biçimini kullanabilirsiniz;
  4. dosyaların yükleme sırası o kadar önemli değil

Modüllerinizi ve dosyalarınızı sıralama seçenekleri

Modülleri bildirmenin ve bunlara erişmenin bu yolu sizi çok esnek kılar. Modülleri işlev türü (başka bir yanıtta açıklandığı gibi) veya rota aracılığıyla sıralayabilirsiniz, örneğin:

/******** sorting by route **********/    
angular.module('home')...
angular.module('another-route')...
angular.module('shared')...

Sonunda nasıl sıralayacağınız, kişisel zevkiniz ve projenin ölçeği ve türü ile ilgilidir. Kişisel olarak, modüllerinizi daha yeniden kullanılabilir hale getirdiği için, tüm farklı test dosyaları da dahil olmak üzere, aynı klasör içindeki bir modülün tüm dosyalarını (yönergelerin, denetleyicilerin, hizmetlerin ve filtrelerin alt klasörlerinde sıralanmıştır) gruplamayı seviyorum. Bu nedenle, orta ölçekli projelerde, diğer projeler için de yararlı olabileceğini düşündüğümde, tüm temel yolları ve bunların kontrolörlerini, hizmetlerini, direktiflerini ve az ya da çok karmaşık alt modülleri içeren bir temel modül elde ederim. :

/******** modularizing feature-sets **********/
/controllers
/directives
/filters
/services
/my-map-sub-module
/my-map-sub-module/controllers
/my-map-sub-module/services
app.js
...

angular.module('app', [
  'app.directives',
  'app.filters',
  'app.controllers',
  'app.services',
  'myMapSubModule'
]);

angular.module('myMapSubModule',[
   'myMapSubModule.controllers',
   'myMapSubModule.services',
   // only if they are specific to the module
   'myMapSubModule.directives',
   'myMapSubModule.filters'
]);

Çok büyük projeler için, bazen modülleri yukarıda açıklandığı gibi rotalara göre veya bazı seçilmiş ana rotalara veya hatta rotaların ve bazı seçilmiş bileşenlerin bir kombinasyonuna göre gruplandırıyorum, ama bu gerçekten bağlıdır.

DÜZENLEME: Sadece ilgili olduğu ve yakın zamanda tekrar karşılaştığım için: Bir modülü yalnızca bir kez oluşturduğunuza dikkat edin (angular.module-function'a ikinci bir parametre ekleyerek). Bu, uygulamanızı bozar ve tespit edilmesi çok zor olabilir.

2015 Modülleri sıralama üzerine DÜZENLEME: Bir buçuk yıllık açısal deneyimden sonra, uygulamanızda farklı adlandırılmış modülleri kullanmanın faydalarının biraz sınırlı olduğunu ekleyebilirim çünkü AMD hala Angular ve hizmetler, direktifler ve filtrelerle gerçekten iyi çalışmıyor her halükarda açısal bağlam içinde küresel olarak mevcuttur ( burada örneklendiği gibi ). Yine de anlamsal ve yapısal bir yararı vardır ve içeri veya dışarı yorumlanmış tek bir kod satırı olan bir modülü dahil etmek / hariç tutmak faydalı olabilir.

Ayrıca , genellikle birbirlerine bağlı olduklarından alt modülleri türe göre ayırmak (ör. 'MyMapSubModule.controllers') neredeyse hiçbir zaman çok mantıklı değildir .


7
IIFE'ye (Anında Çağrılan Fonksiyon İfadesi), yani anonim kendi kendine çalışan fonksiyona ihtiyacınız yok
artı

1
Haklısın. Buna yalnızca "katı kullan" işlev biçimini uygulamak istediğinizde ihtiyacınız vardır; Yine de acıtmıyor.
hugo der hungrige

1
Çoğu durumda 'use strict';bileşeninizin içine de koyabilirsiniz . module.controller(function () { 'use strict'; ... });
Jackson

Uygulamayı seviyorum, ancak zincirleme konusunda da eğlenceli değilim, bu yüzden bunu Beterraba'nın yaptığı şeyle karıştırıyorum
Mirko

1
AMD kullanırken, app adlı tek bir modül yeterlidir. Required ifadesini silerek bir AMD modülü hariç tutulabilir. Ve artık denetleyicileri ve hizmetleri kaydetmemize gerek yok.
James

28

Johnpapa'nın açısal stil kılavuzunu seviyorum ve işte bu soruyla ilgili bazı kurallar:

Kural: Adlandırılmış ve Anonim İşlevler

Anonim işlevleri kullanmaktan kaçının:

// dashboard.js
angular
  .module('app')
  .controller('Dashboard', function() { })

Bunun yerine, adlandırılmış işlevleri kullanın:

// dashboard.js
angular
  .module('app')
  .controller('Dashboard', Dashboard);

function Dashboard() { }

Yazarın dediği gibi: This produces more readable code, is much easier to debug, and reduces the amount of nested callback code.

Kural: Dosya başına 1 bileşen tanımlayın.

Tek bir dosyada birden çok bileşenden kaçının:

angular
  .module('app', ['ngRoute'])
  .controller('SomeController', SomeController)
  .factory('someFactory', someFactory);

function SomeController() { }

function someFactory() { }

Intead, modülü tanımlamak için bir dosya kullanın:

// app.module.js
angular
  .module('app', ['ngRoute']);

bir dosya modülü bir bileşeni tanımlamak için kullanır

// someController.js
angular
  .module('app')
  .controller('SomeController', SomeController);

function SomeController() { }

ve başka bir bileşen tanımlamak için başka bir dosya

// someFactory.js
angular
  .module('app')
  .factory('someFactory', someFactory);

function someFactory() { }

Elbette, modüller, denetleyiciler ve hizmetler için oldukça kullanışlı ve okumaya değer birçok başka kural vardır.

Ve ya_dimon'un yorumu sayesinde, yukarıdaki kod IIFE'ye sarılmalıdır, örneğin:

(function (window, angular) {
  angular.module('app')
   .controller('Dashboard', function () { });
})(window, window.angular);

İyi cevap ve harika bağlantı.
Ellesedil

Farklı javascript dosyalarında farklı denetleyicilerim varsa, daha fazla sayıda dosyanın yani daha fazla sunucu isabetinin yüklenmesini gerektirmez mi?
Vignesh subramanian

Onları yudumla veya homurdanarak, vignesh ile birleştirmek / çirkinleştirmek / yeniden adlandırmak oldukça kolaydır ve kişisel olarak yutkuyu seviyorum.
aqingsao

1
Tüm bu parçacıkların IIFE'de olması gerektiğini eklemeyi unuttunuz, aksi takdirde global olarak "someFactory ()" gibi işlevlere sahipsiniz. İsim çatışmaları için bir şans var. (ve es6'da IIFE'ye ihtiyacınız yok)
ya_dimon

12

Son zamanlarda ben de bu muammayı yaşadım. Ben de sizin gibi zincirleme sözdizimini kullanmaya başlamıştım, ancak uzun vadede büyük projelerde hantal hale geliyor. Normalde ayrı dosyalarda bir denetleyici modülü, bir servis modülü vb. Oluşturur ve bunları başka bir dosyada bulunan ana uygulama modülüme enjekte ederdim. Örneğin:

// My Controllers File
angular.module('my-controllers',[])
    .controller('oneCtrl',[...])
    .controller('twoCtrl',[...]);

// My Services File
angular.module('my-services',[])
    .factory('oneSrc',[...])
    .facotry('twoSrc',[...]);

// My Directives File
angular.module('my-directives',[])
    .directive('oneDrct',[...])
    .directive('twoDrct',[...]);

// My Main Application File
angular.module('my-app',['my-controllers','my-services','my-directives',...]);

Ancak bu dosyaların her biri proje büyüdükçe büyüyordu. Bu yüzden onları her bir denetleyiciye veya hizmete göre ayrı dosyalara ayırmaya karar verdim. angular.module('mod-name').Enjeksiyon dizisi olmadan kullanmanın bunun çalışması için ihtiyacınız olan şey olduğunu buldum . Bir dosyada genel bir değişkeni bildirmek ve bunun başka bir dosyada hazır olmasını beklemek işe yaramaz veya beklenmedik sonuçlar doğurabilir.

Kısacası, başvurum şuna benziyordu:

// Main Controller File
angular.module('my-controllers',[]);

// Controller One File
angular.module('my-controllers').controller('oneCtrl',[...]);

//Controller Two File
angular.module('my-controllers').controller('twoCtrl',[...]);

Bunu hizmetler dosyasına da yaptım, ana uygulama modülü dosyasını değiştirmenize gerek yok, yine de aynı modülleri ona enjekte ediyor olacaksınız.


1
hizmetler / yönergeler / denetleyiciler için ayrı modüller oluşturmanın amacı nedir?
Filip Sobczak

2
Büyük projelerde, denetleyiciler / filtreler / yönergeler / hizmetlerin tümü bir araya getirildiğinde, işler zorlaşabilir. Bu, işleri organize etmenin yalnızca bir yoludur.
meconroy

1
@FilipSobczak Hizmetler / direktifler / kontrolörler için ayrı modüller YARATMAMAKTADIR. Aksine, modülü kullanarak yalnızca bir kez oluşturmuştur angular.module('my-controllers',[]);([] 'yi bildirim için yalnızca bir kez belirttiğini unutmayın). Bunu diğer dosyalarda tekrar kullanıyor. Dosyaların ayrılması, projenin, özellikle de büyüklerin bakımını nispeten kolaylaştırır.
Devner

8

Diğer bir uygulama da denetleyicileri, yönergeleri vb. Kendi modüllerine yerleştirmek ve bu modülleri "ana" modülünüze eklemek:

angular.module('app.controllers', [])
  .controller('controller1', ['$scope', function (scope) {
    scope.name = "USER!";
  }]);

angular.module('app.directives', [])
  .directive('myDirective', [function () {
    return {
      restrict: 'A',
      template: '<div>my directive!</div>'
    }
  }]);

angular.module('app', [
  'app.controllers',
  'app.directives'
]);

Küresel kapsamda hiçbir şey kalmadı.

http://plnkr.co/edit/EtzzPRyxWT1MkhK7KcLo?p=preview


Modül adı olarak neden app.controllersinsted kullanıyorsunuz controllers, herhangi bir avantajı var mı? Angularjs'e yeni geliyorum
sijo vijayan

4

Dosyalarımı ve modüllerimi bölmeyi seviyorum.

Bunun gibi bir şey:

app.js

var myApp = angular.module('myApp', ['myApp.controllers', 'myApp.directives', 'myApp.services']);

myApp.config(['$routeProvider', function($routeProvider) {
    /* routes configs */
    $routeProvider.when(/*...*/);
}]);

directives.js

var myDirectives = angular.module('myApp.directives', []);

myDirectives.directive( /* ... */ );

service.js

var myServices = angular.module('myApp.services', []);

myServices.factory( /* ... */ );

"Zincirleme stil" in büyük bir hayranı değilim, bu yüzden değişkenimi her zaman yazmayı tercih ederim.


2
Bunu yaptığım yol buydu, ancak her services.js veya controller.js dosyası büyük ölçekli bir projede hızla büyüyor, sonunda her hizmeti veya denetleyiciyi ayrı bir dosyaya ayırmanız gerekecek.
meconroy

1
@meconroy Kesinlikle. İş büyüdükçe, yönergeyi daha küçük modüllere ayırmayı ve ardından "ana" yönerge modülüne enjekte etmeyi seviyorum.
Beterraba


0

Benim için zincirleme en kompakt yoldur:

angular.module("mod1",["mod1.submod1"])

 .value("myValues", {
   ...
 })

 .factory("myFactory", function(myValues){
   ...
 })

 .controller("MainCtrl", function($scope){

   // when using "Ctrl as" syntax
   var MC = this;
   MC.data = ...;
 })
 ;

Bu şekilde bileşenleri modüller arasında kolayca taşıyabilirim, aynı modülü asla iki kez bildirmem, hiçbir zaman global değişkenlere ihtiyaç duymam.

Dosya çok uzarsa, çözüm basittir - her biri en üstte kendi modülünü bildiren iki dosyaya bölün. Daha fazla şeffaflık için, dosya başına bir benzersiz modül tutmaya ve dosyanın tam yolunu andıracak şekilde adlandırmaya çalışıyorum. Bu şekilde de hiçbir zaman onsuz bir modül yazmam gerekmiyor [], bu da ortak bir sorun.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.