Насіння AngularJS: розміщення JavaScript в окремих файлах (app.js, controllers.js, direktives.js, filters.js, services.js)


93

Я використовую шаблон кутового насіння, щоб структурувати свою програму. Спочатку я поставив весь мій код JavaScript в один файл, main.js. Цей файл містив мою декларацію модуля, контролери, директиви, фільтри та служби. Додаток працює чудово, як це, але я переживаю за масштабованість та ремонтопридатність, оскільки моя програма стає складнішою. Я помітив, що у шаблону кутового насіння є окремі файли для кожного з них, тому я спробував розповсюдити свій код з одного main.jsфайлу у кожному з інших файлів, зазначених у заголовку, до цього питання та знайдених у app/jsкаталозі кутових -семенний шаблон.

Моє запитання: як мені керувати залежностями, щоб програма почала працювати? Існуюча тут документація не дуже зрозуміла в цьому плані, оскільки кожен із наведених прикладів показує єдиний вихідний файл JavaScript.

Приклад того, що я маю:

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
}

Як мені управляти залежностями?

Заздалегідь спасибі.


2
про це є деякі статті. наприклад, briantford.com/blog/huuuuuge-angular-apps.html , а також деякі проекти, наприклад, yeoman. Є два способи наблизитись до цього: розділення компонентів на шари (на зразок кутового насіння) або за ознаками, як це передбачає деякі статті.
Едуард Гамонал

Коли ви оголошуєте модуль, наприклад, angular.module ('myApp.service1', []), я думаю, вам потрібно додати залежності до [], наприклад, angular.module ('myApp.service1', ['myApp.service2', 'myApp .service2 ']). . Я досить новачок у AngularJS, тому я можу помилитися. Якщо це допоможе, дайте мені знати, і я опублікую відповідь.
Денні Варод

Де слід вставити цей рядок? Я не angular.module('myApp.services', ['myApp.services']);вдав у app.js.
ChrisDevo

@ChrisDevo 1. Коли ви відповідаєте на коментарі, завжди починайте коментар з "@" та імені користувача (без пробілів), щоб користувач отримав сповіщення. 2. myApp.services повинні залежати від інших модулів, а не від себе, наприклад angular.module('myApp.services', ['myApp.server', 'myApp.somethingElse']).
Денні Варод

@DannyVarod, ти редагував попередній коментар? Я читав це як angular.module('myApp.service1', ['myApp.service1', 'myApp.service2'])спочатку. Інакше я б не включив myApp.services як власну залежність.
ChrisDevo

Відповіді:


108

Проблема викликана тим, що ви "передекларували" свій модуль програми у всіх ваших окремих файлах.

Ось як виглядає декларація модуля програми (не впевнений, що декларація є правильним терміном):

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

Ось що таке призначення (не впевнений, чи присвоєння є правильним терміном) вашому модулю програми виглядає так:

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

Зауважте відсутність квадратних дужок.

Отже, колишню версію, одну з квадратними дужками, слід використовувати лише один раз, як правило, у вашому app.jsабо main.js. Усі інші пов'язані файли - контролери, директиви, фільтри ... - повинні використовувати останню версію, таку, яка не має квадратних дужок.

Сподіваюся, це має сенс. Ура!


9
Я знайшов рішення цього питання. Здається, що потрібен лише один модульmyApp . У своєму файлі app.js я створив var для нього. var myApp = angular.module('myApp', []);У всіх інших файлах я просто посилався на цей var (наприклад, myApp.filter('myFilter', function(MyService) { /* filter code */ });доки я додав імена файлів у теги скриптів у своєму html, мені не потрібно було декларувати жодного іншого Шаблон проекту кутового насіння в цьому плані досить заплутаний
ChrisDevo

1
Зараз я справді розгублений. Я пішов назад і видалити глобальні змінні myApp, так що тепер анонімний модуль app.js: angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'myApp.controllers']);. У всіх інших файлах я також оголосив такі анонімні модулі angular.module('myApp.filter', []).filter('myFilter', function(MyService) { /* filter code */ });. Зараз моє додаток працює так. Я переглянув свою історію коду і не можу побачити, де це щось інше, ніж те, що я, коли він не працював.
ChrisDevo

4
Обіцяю, що це працює. Я використовую його щодня, розробляючи програми Angular Apps. Знову я маю одне оголошення angular.module('myApp', []);(помітьте квадратні дужки) у своєму головному файлі js. Потім усі інші файли відносяться до модуля за допомогою синтаксису angular.module('myApp').controllerабо .directive.
Джастін Л.

5
Помилки викликані тим, що Angular шукає модулі під назвою myApp.controller, myApp.filters… але, це не модулі, вони є компонентами, що розширюють один модуль, який називається myApp. Все має спрацювати, якщо ви видалите всі свої myApp.залежно від залежності вашого модуля. Дотримуйтесь порожніх квадратних дужок (якщо ви не включаєте інші справжні кутові модулі, наприклад ngCookies, ngResource) при оголошенні основного модуля програми:angular.module('myApp', []);
Джастін Л.

1
Ага, гаразд. Розмістивши їх в якості залежно для модуля додатка, це буде помилка , тому що він має , щоб знайти їх. Якщо ви виймете їх із квадратних дужок, ви можете завантажити їх за бажанням, і ваш додаток не хвилюватиметься. ngResourceце, безумовно, одна з тих, які ви розміщуєте в своїх дужках декларацій модуля. Якщо моя відповідь допомогла, голосування та схвалення було б дуже вдячно.
Джастін Л.

12

Якщо ви хочете помістити різні частини своєї програми ( filters, services, controllers) у різні фізичні файли, вам потрібно зробити дві речі:

  1. Задекларуйте ці простори імен (через відсутність кращого терміна) у вашому app.js або у кожному файлі;
  2. Зверніться до тих просторів імен у кожному з файлів.

Отже, ваше app.jsвиглядатиме так:

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

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

І в кожному окремому файлі:

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...
});

Все це можна об'єднати в один дзвінок:

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

Важлива частина полягає в тому, що ви не повинні переосмислювати angular.module('myApp'); це призведе до того, що він буде перезаписаний, коли ви інстанціюєте контролери, ймовірно, не те, що вам потрібно.


1
Мені подобається такий підхід, ви можете використовувати його для створення багаторівневої структури (скажімо, вашому контролеру потрібна послуга або фільтр). Зауважте, я також виявив, що після введення субзалежності (як, наприклад, цей фільтр для контролера) він також доступний для всіх батьків вище (якщо візуалізується як дерево) без повторного оголошення ін'єкції, просто не вводьте " не забудьте про це, якщо ви змінили дитину і використовуєте її у батьків. Також я рекомендую ніколи не ставити більше одного модуля (простору імен) у файл і ніколи не намагатися використовувати одне і те ж простір імен у кількох файлах.
Гері

Що робити, якщо у мене два файли контролера або два сервісні файли? Чи буде екземпляр траплятися для кожного окремого файлу?
Avinash Raj

3

Ви отримуєте помилку, оскільки ви ще не визначилися myApp.services. Що я робив до цього часу, - це помістити всі початкові визначення в один файл, а потім використовувати їх в іншому. Як і для вашого прикладу, я би вклав:

app.js

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

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

Це повинно позбутися помилки, хоча, я думаю, ви повинні прочитати статтю Едуарда Гамонала, згадану в одному з коментарів.


Дякую, Торстене, але я прочитав цю статтю і додав рядок angular.module('myApp.services', []);у свій файл app.js. Жоден із нас не вирішує мою проблему.
ChrisDevo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.