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

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

问题描述

是否有可能从一个角度控制器装入普通老JS或AMD模块?我有previously使用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堆栈种子一个新的项目,而这不使用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.

我不完全清楚,但角度对加载模块的系统 - 我可以从我的角度控制器中加载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?

有没有修改我的模块()声明,包括其他常规的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-包括(它加载子窗体)加载。

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.

推荐答案

好吧,我评论我的code,以便它应该解释一切。如果你有任何问题,只是让我知道。这是解决在您的意见,进一步说明了问题。这里现场演示(点击进入)。

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

有很多,你可以实现我在这里展示的概念的方式。试想想,你想如何使用它,并写一些指令来实现它。角使得大多数事情pretty简单。

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.

注意:注射脚本标记是可选的 - 但我大大preFER的,而不是直接执行脚本。当使用script标签,你就可以在脚本一节中来跟踪所有以资源下的开发工具加载的文件。

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.

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

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