AngularJS çekirdeği: JavaScript'i ayrı dosyalara yerleştirme (app.js, controllers.js, directives.js, filters.js, services.js)


93

Uygulamamı yapılandırmak için açısal çekirdek şablonunu kullanıyorum . Başlangıçta tüm JavaScript kodumu tek bir dosyaya koyuyorum main.js. Bu dosya benim modül bildirimimi, denetleyicileri, yönergeleri, filtreleri ve hizmetleri içeriyordu. Uygulama böyle iyi çalışıyor, ancak uygulamam daha karmaşık hale geldikçe ölçeklenebilirlik ve sürdürülebilirlik konusunda endişeliyim. Açısal çekirdek şablonunun bunların her biri için ayrı dosyalara sahip olduğunu fark ettim, bu yüzden kodumu tek main.jsdosyadan bu soruya başlıkta belirtilen app/jsve açısal dizinde bulunan diğer dosyaların her birine dağıtmaya çalıştım. tohum şablonu.

Sorum şu: uygulamayı çalıştırmak için bağımlılıkları nasıl yönetirim? Burada bulunan mevcut belgeler , verilen örneklerin her biri tek bir JavaScript kaynak dosyası gösterdiğinden bu konuda çok açık değildir.

Sahip olduğum şeye bir örnek:

app.js

angular.module('myApp', 
    ['myApp.filters',
     'myApp.services',
     'myApp.controllers']);

controllers.js

angular.module('myApp.controllers', []).
    controller('AppCtrl', [function ($scope, $http, $filter, MyService) {

        $scope.myService = MyService; // found in services.js

        // other functions...
    }
]);

filters.js

angular.module('myApp.filters', []).
    filter('myFilter', [function (MyService) {
        return function(value) {
            if (MyService.data) { // test to ensure service is loaded
                for (var i = 0; i < MyService.data.length; i++) {
                    // code to return appropriate value from MyService
                }
            }
        }
    }]
);

services.js

angular.module('myApp.services', []).
    factory('MyService', function($http) {
        var MyService = {};
        $http.get('resources/data.json').success(function(response) {
            MyService.data = response;
        });
        return MyService;
    }
);

main.js

/* This is the single file I want to separate into the others */
var myApp = angular.module('myApp'), []);

myApp.factory('MyService', function($http) {
    // same code as in services.js
}

myApp.filter('myFilter', function(MyService) {
    // same code as in filters.js
}

function AppCtrl ($scope, $http, $filter, MyService) {
    // same code as in app.js
}

Bağımlılıkları nasıl yönetirim?

Şimdiden teşekkürler.


2
bununla ilgili bazı makaleler var. örneğin briantford.com/blog/huuuuuge-angular-apps.html ve yeoman gibi bazı projeler. buna yaklaşmanın iki yolu vardır: bazı makalelerin önerdiği gibi bileşenleri katmanlara (açısal çekirdek gibi) veya özelliğe göre ayırmak.
Eduard Gamonal

Örneğin angular.module ('myApp.service1', []) gibi bir modül bildirdiğinizde , [] örn. Angular.module'a ('myApp.service1', ['myApp.service2', 'myApp) bağımlılıklar eklemeniz gerektiğini düşünüyorum. .service2 ']). . AngularJS'de oldukça yeniyim, bu yüzden yanılıyor olabilirim. Bu işe yararsa bana bildirin ve bir cevap göndereceğim.
Danny Varod

Bu satır nereye eklenmelidir? angular.module('myApp.services', ['myApp.services']);Hiç şansım olmadan app.js'ye koydum .
ChrisDevo

@ChrisDevo 1. Yorumlara cevap verdiğinizde, yoruma her zaman '@' ve kullanıcının adı (boşluksuz) ile başlayın, böylece kullanıcı bir bildirim alır. 2. myApp.services kendine değil, diğer modüllere bağlı olmalıdır, örn angular.module('myApp.services', ['myApp.server', 'myApp.somethingElse']).
Danny Varod

@DannyVarod, önceki yorumunuzu düzenlediniz mi? angular.module('myApp.service1', ['myApp.service1', 'myApp.service2'])Orijinal olarak okudum . Aksi takdirde myApp.services'i kendi bağımlılığı olarak dahil etmezdim.
ChrisDevo

Yanıtlar:


108

Sorun, uygulama modülünüzü tüm ayrı dosyalarınızda "yeniden bildirmenizden" kaynaklanır.

Uygulama modülü bildirimi (bildirim doğru terim olduğundan emin değil) şöyle görünür:

angular.module('myApp', []).controller( //...

Uygulama modülünüze atamanın (atamanın doğru terim olup olmadığından emin değilsiniz) şu şekilde görünür:

angular.module('myApp').controller( //...

Köşeli parantezlerin eksikliğine dikkat edin.

Bu nedenle, köşeli parantez içeren eski sürüm yalnızca bir kez kullanılmalıdır, genellikle app.jsveya main.js. Diğer tüm ilişkili dosyalar - denetleyiciler, yönergeler, filtreler … - köşeli parantez içermeyen ikinci sürümü kullanmalıdır .

Umarım bu mantıklıdır. Şerefe!


9
Bu soruna bir çözüm buldum. Görünüşe göre sadece bir modüle ihtiyaç var myApp. App.js dosyamda bunun için bir var oluşturdum var myApp = angular.module('myApp', []);. Diğer tüm dosyalarda bu değişkenden bahsettiğim (örneğin, myApp.filter('myFilter', function(MyService) { /* filter code */ });dosya adlarını html'imdeki komut dosyası etiketlerine eklediğim sürece, başka herhangi bir Açısal tohum proje şablonu bu açıdan oldukça kafa karıştırıcı.
ChrisDevo

1
Şimdi gerçekten kafam karıştı. Arka tarafı gitmiş ve global var kaldırdık myAppartık isimsiz bir modüldür böylece, app.js: angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'myApp.controllers']);. Diğer tüm dosyalarda da bunun gibi anonim modüller tanımladım angular.module('myApp.filter', []).filter('myFilter', function(MyService) { /* filter code */ });. Uygulamam artık bu şekilde çalışıyor. Kod geçmişimi gözden geçirdim ve bunun nerede çalışmadığımdan farklı olduğunu göremiyorum.
ChrisDevo

4
Söz veriyorum bu işe yarıyor. Angular Apps geliştirirken her gün kullanıyorum. Yine, angular.module('myApp', []);ana js dosyamda bir bildirimim var (köşeli parantezlere dikkat edin). Ardından, diğer tüm dosyalar angular.module('myApp').controllerveya .directivesözdizimini kullanarak modüle başvurur .
Justin L.

5
Hataların sebebi Angular'ın myApp.controller, myApp.filters… ama bunlar modüller değil, myApp adlı bir modülü genişleten bileşenlerdir. Modül bağımlılıklarınızdan tüm myApp.wher ne olursa olsun kaldırırsanız her şey çalışmalıdır. Ana uygulama modülünüzü bildirirken köşeli parantezleri boş tutun (örneğin ngCookies, diğer gerçek açısal modülleri dahil etmiyorsanız ngResource):angular.module('myApp', []);
Justin L.

1
Ah tamam. Bunları uygulama modülünüz için bir bağımlılık olarak yerleştirdiğinizde, onları bulması gerektiği için hata verecektir. Onları köşeli parantezlerden çıkarırsanız, istediğiniz zaman yükleyebilirsiniz ve uygulamanızın umurunda olmaz. ngResourcekesinlikle modül bildirim parantezlerinize koyduğunuzlardan biridir. Cevabım yardımcı olsaydı, oy vermek ve onaylamak çok hoş olurdu.
Justin L.

12

Uygulamanızın farklı bölümlerini ( filters, services, controllers) farklı fiziksel dosyalara koymak istiyorsanız, yapmanız gereken iki şey vardır:

  1. Bu ad alanlarını (daha iyi bir terim olmadığı için) sizin app.jsveya her dosyanızın içinde bildirin;
  2. Dosyaların her birinde bu ad alanlarına bakın.

Yani, app.jsşuna benzeyeceksin:

angular.module('myApp', ['external-dependency-1', 'myApp.services', 'myApp.controllers'])
.run(function() {
   //...

})
.config(function() {
  //...
});

Ve her bir dosyada:

services.js

angular.module('myApp.services', []); //instantiates
angular.module('myApp.services') //gets
.factory('MyService', function() { 
  return {};
});

controllers.js

angular.module('myApp.controllers', []); //instantiates
angular.module('myApp.controllers')      //gets
.controller('MyCtrl', function($scope) {
  //snip...
})
.controller('AccountCtrl', function($scope) {
  //snip...
});

Tüm bunlar tek bir aramada birleştirilebilir:

controllers.js
angular.module('myApp.controllers', []) 
.controller('MyCtrl', function($scope) {
 //snip...
});    

Önemli olan, yeniden tanımlamamanız gerektiğidir angular.module('myApp'); bu, denetleyicilerinizi somutlaştırdığınızda üzerine yazılmasına neden olur, muhtemelen istediğinizi değil.


1
Bu yaklaşımı beğendim, katmanlı bir yapı oluşturmak için kullanabilirsiniz (denetleyicinizin bir hizmete veya filtreye ihtiyacı olduğunu söyleyin). Not, ayrıca bir alt bağımlılık (bir denetleyici için filtre gibi) enjekte edildiğinde, enjeksiyonu yeniden bildirmeden yukarıdaki tüm ebeveynlerde de (bir ağaç olarak görselleştiriliyorsa) mevcut olduğunu buldum, sadece yapmayın ' Çocuğu değiştirirseniz ve ebeveynde kullanıyorsanız, unutun. Ayrıca, bir dosyaya birden fazla modül (ad alanı) koymamayı ve aynı ad alanını asla birden fazla dosyada kullanmayı denememenizi tavsiye ederim.
Gary

Ya iki denetleyici dosyam veya iki hizmet dosyam varsa? Örnekleme her bir dosya için gerçekleşecek mi?
Avinash Raj

3

myApp.servicesHenüz tanımlamadığınız için hatayı alıyorsunuz . Şimdiye kadar yaptığım şey, tüm ilk tanımları bir dosyaya koymak ve sonra bunları başka bir dosyada kullanmak. Örneğin sizin örneğiniz için şöyle yazacağım:

app.js

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

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

Bu, hatadan kurtulmalı, ancak yorumlardan birinde bahsedilen Eduard Gamonal makalesini okumalısınız .


Teşekkürler Torsten, ama bu makaleyi okudum ve satırı angular.module('myApp.services', []);app.js dosyama ekledim. Benim sorunum gerçekten çözülmüyor.
ChrisDevo
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.