Как ленить загружать файлы без angular JavaScript с помощью AngularJS?

Можно ли загружать старые старые модули JS или AMD из контроллера Angular? Я ранее использовал RequireJS для этого.

Я использовал AngularJS и RequireJS на довольно большом проекте раньше. Я работаю над новым проектом, основанным на семенах MEAN Stack, и это не использует requireJS.

Я не совсем понимаю, но Angular имеет систему для загрузки модулей - могу ли я загрузить конкретный кусок javascript из моего контроллера Angular?

Есть ли способ изменить мое объявление module(), чтобы включить дополнительные обычные файлы javascript?

Спасибо!

EDIT: Чтобы немного понять, что я делаю, у меня есть страница, которая редактирует несколько разных форм. Каждый из них сохраняется в моей базе данных как "форма". В зависимости от типа формы различные значения словаря отображаются в разные поля в разных под-представлениях. Некоторые из моих форм имеют, например, раскрывающиеся списки или списки входов. Они разные, но все остальное о "форме" обрабатывается общим образом.

Итак, у меня есть этот сингулярный контроллер формы, который обрабатывает кучу разных форм, и я очень доволен результатом. Основная проблема заключается в том, что каждая форма имеет отдельный набор данных, которые я бы хотел избежать загрузки, если только мне это нужно.

Я могу проверить, какую форму я загружаю, установив мой раскрывающийся список, который управляет моим ng-include (который загружает подчиненную форму).

В краткосрочной перспективе я только что загрузил все и создал пространства имен в моей области действия, чтобы различать.

например, $scope.form1 и $scope.form2 для данных/правил, специфичных для конкретной формы. Я бы так же скоро не загрузил js, который мне не нужен.

Изменить 2: http://jsfiddle.net/HB7LU/1320/

function MyCtrl($scope) {       
    $scope.doSomething = function()
    {
     //I'm used to wrapping with e.g require('jquery..... here, can I do the same thing with angular?   
        alert(" I need to run a jquery function here...");
        var xml = $(someblock);
    };
}

Я поставил скрипку с тем, о чем я говорю. Я хочу загрузить произвольную JS в зависимости от определенных путей в моем контроллере и только тогда, когда они мне нужны.

В основном у меня есть несколько больших пространств имен, которые я хочу загрузить, в зависимости от одного из множества выбранных параметров, и было бы дорого просто загрузить их все.

Ответ 1

Хорошо, я прокомментировал свой код, чтобы он все объяснил. Если у вас есть дополнительные вопросы, просто дайте мне знать. Это решение проблем, как это описано в ваших комментариях. Живая демонстрация здесь (нажмите).

Разметка:

<!DOCTYPE html>
<html ng-app="myApp" ng-controller="myCtrl">
<head>
</head>
<body>

  <button ng-click="load()">Load Foo</button>
  <!-- I'm using this to bootstrap the lazy loaded script -->
  <section ng-repeat="item in loaded" lazy="item"></section>

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script>  
<script src="script.js"></script>
</body>
</html>

JavaScript:

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

app.controller('myCtrl', function($scope) {
  //array of things to load
  $scope.lazyThings = [
    {directive:'my-foo-directive', file:'foo.js'}  
  ];
  $scope.loaded = [];
  $scope.load = function() {
    var loadIndex = $scope.loaded.length;
    if ($scope.lazyThings[loadIndex]) {
      $scope.loaded.push($scope.lazyThings[loadIndex]);
    }
  }
});

app.factory('myService', function($http) {
  return {
    getJs: function(path) {

      return $http.get(path).then(function(response) {
        deferred.resolve(response.data);
      });

    }
  }
});

//this adds an attribute to kick off the directive 
//for whatever script was lazy loaded
app.directive('lazy', function($compile, $q, myService) {
  var directiveReturn = {
    restrict: 'A',
    scope: {
      lazy: '='
    },
    link: function(scope, element) {
      myService.getJs(scope.lazy.file).then(function(data) {
        return addScript(scope.lazy.file, data, scope);
      }).then(function() {
        var $span = angular.element('<span></span>').attr(scope.lazy.directive, '');
        $compile($span)(scope);
        element.append($span);
      });
    }
  }

  var scriptPromises = {};
  function addScript(file, js, scope) {
    if (!scriptPromises[file]) { //if this controller hasn't already been loaded
      var deferred = $q.defer();
      //cache promise)
      scriptPromises[file] = deferred.promise;

      //inject js into a script tag
      var script = document.createElement('script');
      script.src = 'data:text/javascript,' + encodeURI(js);
      script.onload = function() {
        //now the script is ready for use, resolve promise to add the script directive element
        scope.$apply(deferred.resolve());
      };
      document.body.appendChild(script);
      return deferred.promise;
    }
    else { //this script has been loaded before
      return scriptPromises[loadFile]; //return the resolved promise from cache
    }
  }

  return directiveReturn;
});

app.directive('myFooDirective', function() {
  return {
    restrict: 'A',
    link: function(scope, element) {
      //put the logic from your lazy loaded "foo.js" script here
      element.text(foo.someFunction());
    }
  }
});

Пример ленивой загрузки script:

var foo = {
  someFunction: function() {
    return 'I am data from a lazy loaded js function!';
  }
};

Существует множество способов реализовать концепцию, которую я продемонстрировал здесь. Просто подумайте о том, как вы хотели бы использовать его, и напишите некоторые директивы для его выполнения. Angular делает большинство вещей довольно простыми.

Примечание. Ввод тега script не является обязательным, но я предпочитаю это скорее, чем выполнение script напрямую. При использовании тега script вы сможете отслеживать все загруженные файлы с помощью инструментов dev в разделе "Ресурсы" в разделе "Скрипты".

Ответ 2

Собственно, я мало знаю о директивах angular и это модульные вещи, но с моими базовыми знаниями я создаю некоторую функцию предварительной загрузки для загрузки моих файлов JS.... Функция loadScript определена в моем приложении app.js, который включен в основную страницу html.

function loadScript(src,callback){

    var script = document.createElement("script");
    script.type = "text/javascript";
    if(callback)script.onload=callback;
    document.getElementsByTagName("head")[0].appendChild(script);
    script.src = src;
}

внутри контроллера используйте что-то вроде этого

app.controller('myCtrl', function($scope) {
  //array of things to load are saved in a JavascriptFile
  loadScript("URL_To_JavascriptFile");
});

Ответ 3

Angular модульная система не похожа на RequireJS. Angular относится только к определению модуля и его составу, но не к загрузке модуля.

Это означает, что Angular не выдаст HTTP-запрос для загрузки любого javascript, вы несете ответственность за его загрузку, используя теги <script> или другой загрузчик javascript, например requirejs.

Кроме того, Angular требует, чтобы все модули загружались и настраивались до того, как приложение Angular загрузилось. Это затрудняет поддержку каких-либо схем ленивой загрузки для модулей Angular.

Создание Angular возможности иметь дело с более динамической загрузкой модулей - это запланированное для будущих выпусков.