如何使用 AngularJS 延迟加载非角度 JavaScript 文件? [英] How to Lazy load non-angular JavaScript files using AngularJS?

查看:16
本文介绍了如何使用 AngularJS 延迟加载非角度 JavaScript 文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以从 Angular 控制器加载普通的旧 JS 或 AMD 模块?我以前为此使用过 RequireJS.

Is it possible to load plain old JS or AMD modules from an Angular Controller? I have previously used RequireJS for this.

我之前在一个相当大的项目中使用过 AngularJS 和 RequireJS.我正在开发一个基于 MEAN Stack 种子的新项目,这不使用 requireJS.

I have used AngularJS and RequireJS on a fairly large project before. I am working on a new project based on the MEAN Stack seed, and this does not use requireJS.

我不是很清楚,但 Angular 有一个加载模块的系统——我可以从我的 angular 控制器中加载特定的 javascript 片段吗?

I am not entirely clear, but Angular has a system for loading modules -- can I load a particular piece of javascript from within my angular controller?

有没有办法修改我的 module() 声明以包含其他常规 javascript 文件?

Is there a way to modify my module() declaration to include additional regular javascript files?

谢谢!

为了对我正在做的事情有一点了解,我有一个页面可以编辑几个不同的表单.这些中的每一个都作为表单"保存到我的数据库中.根据表单的类型,不同的字典值映射到不同子视图中的不同字段.我的一些表单具有例如下拉列表或输入列表.这些是不同的,但有关表单"的所有其他内容都以通用方式处理.

To give a bit of understanding on what I am doing, I have a page that edits a few different forms. Each of these is saved into my database as a "form". Depending on the type of form, different dictionary values are mapped to different fields in different sub-views. Some of my forms have e.g dropdowns or lists of inputs. These are different, but everything else about the 'form' is handled in a generic way.

所以我有这个单一的表单控制器来处理一堆不同的表单,我对结果非常满意.主要问题来自每个表单都有一组单独的数据,除非我需要,否则我希望避免加载.

So I have this singular form controller that handles a bunch of different forms, and I am very happy with the result. The main issue comes from that each form has a separate set of data I would like to avoid loading unless I need.

我可以通过检查驱动我的 ng-include(加载子表单)的下拉列表来检查我正在加载哪个表单.

I can check which form I am loading by checking my dropdown that drives my ng-include (which loads the subform).

在短期内,我刚刚加载了所有内容并在我的范围内创建了命名空间以进行区分.

In the short term I have just loaded everything and created namespaces under my scope to differentiate.

例如 $scope.form1 和 $scope.form2 用于特定表单的数据/规则.我宁愿不加载我不需要的 js.

e.g $scope.form1 and $scope.form2 for data/rules specific to a particular form. I'd just as soon rather not load the js that I don't need.

编辑 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,并且仅在我需要它们时加载.

I've put up a fiddle with exactly what I am talking about. I want to load arbitrary JS depending on certain paths in my controller, and only when I need them.

基本上,我有一些更大的命名空间,我想根据选择的众多选项之一加载它们,并且将它们全部加载会很昂贵.

Basically I have some larger namespaces I want to load depending on one of many options selected, and it would be expensive to just load them all.

推荐答案

好的,我注释了我的代码,以便它可以解释所有内容.如果您有任何其他问题,请告诉我.这是您的评论中进一步解释的问题的解决方案.现场演示(点击).

Ok, I commented my code so that it should explain everything. If you have any further questions, just let me know. This is the solution to the issues as are further explained in your comments. Live demo here (click).

标记:

<!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's 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());
    }
  }
});

延迟加载脚本示例:

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

有很多方法可以实现我在此处演示的概念.想想你想如何使用它,并编写一些指令来执行它.Angular 让大多数事情变得非常简单.

There are plenty of ways that you could implement the concept I demonstrated here. Just think about how you would like to use it, and write some directives to carry it out. Angular makes most things pretty simple.

注意: 注入脚本标记是可选的 - 但我更喜欢这样做而不是直接执行脚本.使用脚本标签时,您将能够使用脚本"部分的资源"下的开发工具跟踪所有加载的文件.

Note: Injecting the script tag is optional - but I greatly prefer that rather than executing the script directly. When using the script tag, you will be able to track all of the loaded files with the dev tools under "Resources" in the "Scripts" section.

这篇关于如何使用 AngularJS 延迟加载非角度 JavaScript 文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆