Подтвердить что ты не робот

AngularJS - динамическая загрузка внешних JS на основе маршрутов

Я пытаюсь сделать простое одностраничное мобильное приложение с несколькими представлениями и кнопкой "\ назад" для управления каждым просмотром. Я использую библиотеку Angular Mobile UI.

Основной макет выглядит следующим образом:

<html>
    <head>
        <link rel="stylesheet" href="mobile-angular-ui/dist/css/mobile-angular-ui-base.min.css">
        <link rel="stylesheet" href="mobile-angular-ui/dist/css/mobile-angular-ui-desktop.min.css">

        <script src="js/angular/angular.min.js"></script>
        <script src="js/angular/angular-route.min.js"></script>
        <script src="mobile-angular-ui/dist/js/mobile-angular-ui.min.js"></script>

        <script src="app/app.js"></script>
        <script src="app/firstController.js"></script>
        <script src="app/secondController.js"></script>
        <script src="app/thirdController.js"></script>

    </head>

    <body ng-app="demo-app">
        <div ng-view></div>

        <div ng-controller="nextBackController" class="navbar navbar-app navbar-absolute-bottom">
            <div class="btn-group justified">
              <a href="#/" class="btn btn-navbar btn-icon-only"><i class="fa fa-home fa-navbar"></i></a>
              <a href="#/second" class="btn btn-navbar btn-icon-only"><i class="fa fa-list fa-navbar"></i></a>
            </div>
        </div>

    </body>


</html>

App.js выглядит следующим образом:

var app = angular.module('demo-app', [
  "ngRoute",
  "mobile-angular-ui"
]);

app.config(function($routeProvider) {
  $routeProvider.when('/', { controller: "firstController",
                             templateUrl: "views/first.html"});
  $routeProvider.when('/', { controller: "secondController",
                             templateUrl: "views/first.html"});
  $routeProvider.when('/', { controller: "thirdController",
                             templateUrl: "views/first.html"});
});

controllers = {};

controllers.nextBackController = function($scope, $rootScope) {
    //Simple controller for the next, back buttons so we just put it in app.js
};

app.controller(controllers);

firstController.js будет содержать что-то похожее на:

controllers.firstController = function($scope) {
    //Do our logic here!!!
};

Проблема в том, что если вы заметите в верхней части HTML-страницы, мне нужно загрузить все контроллеры. Это не масштабируется. Я хочу, чтобы каждый контроллер находился в своем собственном JS файле и не должен был статически загружать каждый из них, поскольку пользователь может даже не потребовать этот контроллер. Есть ли способ динамически загружать реальный файл JS при переключении маршрутов? или я могу прикрепить тег сценария вверху моего файла "first.html", "second.html" и т.д.

4b9b3361

Ответ 1

Если я правильно понимаю, вам нужно загрузить конкретные сценарии для каждого представления? Я делюсь этим фрагментом из личного проекта, который использует ocLazyLoader плагин, который загружает модули по требованию.

var myApp = angular.module("myApp", [
"ui.router", 
"oc.lazyLoad",  
]); 

тогда в вашей маршрутизации вы можете загрузить динамические файлы JS/CSS соответственно, в этом примере я загружаю зависимости плагина UI Select

myApp.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {

$stateProvider

  // State
    .state('demo', {
        url: "/demo.html",
        templateUrl: "views/demo.html",
        data: {pageTitle: 'demo page title'},
        controller: "GeneralController",
        resolve: {
            deps: ['$ocLazyLoad', function($ocLazyLoad) {
                return $ocLazyLoad.load([{
                    name: 'ui.select',
 // add UI select css / js for this state
                    files: [
                        'css/ui-select/select.min.css', 
                        'js/ui-select/select.min.js'
                    ] 
                }, {
                    name: 'myApp',
                    files: [
                        'js/controllers/GeneralController.js'
                    ] 
                }]);
            }]
        }
    })

Ответ 2

Если вы знакомы с Grunt:

https://github.com/ericclemmons/grunt-angular-templates

Используйте Grunt и вышеуказанную задачу сборки для создания одного .js из всех представлений. Включите прослушиватель задач наблюдения за всеми html файлами в каталоге представлений. Всякий раз, когда делается изменение в отношении частичных представлений, создается запись "$ templateCache" со всем html в файле и URL-адрес для псевдонима кеша. Ваши маршруты будут указывать на частичные представления таким же образом, но html файлы не обязательно должны присутствовать. Только файл .js с шаблонами. Красота заключается в том, что он загружается один раз и доступен на стороне клиента для всего сеанса. Это сокращает количество HTTP-звонков, и ваш трафик может быть уменьшен только на вызовы веб-сервисов.

Это пример шаблона из ссылки github, выше:

angular.module('app').run(["$templateCache", function($templateCache) {
$templateCache.put("home.html",
// contents for home.html ...
);
...
$templateCache.put("src/app/templates/button.html",
// contents for button.html
);
}]);

Если вы не знакомы с Grunt

Проверьте это. Это довольно бесценно для автоматизации сборки, минимизации, конкатенации, транспиляции и т.д.

http://gruntjs.com/

Ответ 3

Если ваше приложение не является МАССИВНЫМ, вы должны ДЕЙСТВИТЕЛЬНО избегать подачи небольших файлов js по отдельности. Это заметно замедлит ваше приложение, даже если вы должны найти способ лениво извлекать файлы по мере необходимости, как вы предлагаете в своем вопросе.

Гораздо лучший способ сделать это (и способ, используемый и предложенный командой AngularJS) состоит в том, чтобы иметь ПРОЦЕСС BUILD (вы должны использовать grunt для этого) объединить все ваши файлы javascript и обслуживать их как единый Файл app.js. Таким образом, вы можете поддерживать организованную базу кода с таким количеством крошечных js файлов, сколько хотите, но уменьшите выбор script до одного запроса.

Ответ 4

Как установить OCLazyLoad.

1. Скачайте ocLazyLoad.js здесь

Его можно найти в папке "dist" в репозитории git. Вы также можете установить его с помощью bower install oclazyload или npm install oclazyload.

2. Добавьте модуль oc.lazyLoad в ваше приложение:

var myApp = angular.module("MyApp", ["oc.lazyLoad"]);

3. Загружайте свои JS файлы по запросу на основе маршрутов:

    myApp.controller("MyCtrl", function($ocLazyLoad){
       $ocLazyLoad.load('testModule.js');
    }});`

С помощью $ocLazyLoad вы можете загружать модули angular, но если вы хотите загрузить любой компонент (контроллеры/службы/фильтры/...) без определения нового модуля, это вполне возможно (просто убедитесь, что вы определяете это компонент в существующем модуле).

Существует несколько способов использовать $ocLazyLoad для загрузки ваших файлов, просто выберите тот, который вы предпочитаете.

Также не забывайте, что если вы хотите начать работу, а документов недостаточно, см. примеры в папке "примеры"!

Быстрый старт

Ответ 5

Я не уверен, как это работает в стандартном Angular, однако, вы можете использовать Angular-UI-Router:

Контроллеры создаются по мере необходимости, когда создаются соответствующие им области, т.е. Когда пользователь вручную переходит к состоянию через URL, $ stateProvider загружает правильный шаблон в представление, а затем привязывает контроллер к области действия шаблона.

https://github.com/angular-ui/ui-router/wiki

Ответ 6

RequireJS может быть действительно полезным в этом случае. Вы можете объявлять зависимости ваших JS файлов с помощью RequireJS.

Вы можете отправить этот простой учебник.