AngularJS - 基于路由动态加载外部JS

时间:2014-05-14 13:34:50

标签: javascript jquery html angularjs

我对Angular很新。我看了一些教程并阅读了一些文档。我现在开始弄脏手了。我正在尝试制作一个包含多个视图的简单单页移动应用程序和一个用于控制每个视图的下一个\ back按钮。我正在使用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文件?或者我可以在我的&#34; first.html&#34;,&#34; second.html&#34;等的顶部贴上脚本标签。

7 个答案:

答案 0 :(得分:22)

如果我理解正确,您需要为每个视图加载特定的脚本?我正在使用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'
                    ] 
                }]);
            }]
        }
    })

我希望这很有用..

答案 1 :(得分:7)

如果您熟悉Grunt:

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

使用Grunt和上面的构建任务从所有视图创建一个.js。在视图目录中的所有html文件中包含监视任务侦听器。每当对任何部分视图进行更改时,都会出现&#34; $ templateCache&#34;使用文件中的所有html和用于别名缓存的URL创建条目。您的路线将以相同的方式指向部分视图,但不需要存在html文件。只有带有模板的.js文件。这样做的好处在于它可以加载一次,并且可以在客户端进行整个会话。这减少了http呼叫,您的流量只能减少到Web服务呼叫。

以上是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/

答案 2 :(得分:5)

除非您的应用 MASSIVE ,否则您应该真的避免单独提供小型js文件。这将显着减慢您的应用程序,即使您想要根据您的问题建议根据需要找出懒惰获取文件的方法。

更好的方法(以及AngularJS团队使用和建议的方式)是使用BUILD PROCESS(你应该使用grunt)连接所有的javascript文件,并将它们作为一个app.js文件。这样,您可以根据需要使用尽可能多的小js文件维护有组织的代码库,但将脚本提取减少到单个请求。

答案 3 :(得分:4)

如何安装OCLazyLoad。

<强> 1。下载ocLazyLoad.js here

可以在git存储库的'dist'文件夹中找到它。您也可以使用bower install oclazyloadnpm install oclazyload安装它。

<强> 2。将模块oc.lazyLoad添加到您的应用程序:

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

第3。根据路线按需加载JS文件:

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

使用$ocLazyLoad可以加载角度模块,但如果要加载任何组件(controllers / services / filters / ...)而不定义新模块,则完全可以(只需确保定义此模块)现有模块中的组件。)

有多种方法可以使用$ocLazyLoad加载文件,只需选择您喜欢的文件。

另外请不要忘记,如果您想要开始使用并且文档不够,请参阅“examples”文件夹中的示例!

Quick Start

答案 4 :(得分:1)

我不确定它在标准角度下是如何工作的,但是,你可以使用angular-ui-router:

 "Controllers are instantiated on an as-needed basis, when their corresponding 
 scopes are created, i.e. when the user manually navigates to a state via a URL,
 $stateProvider will load the correct template into the view, then bind the
 controller to the template's scope."

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

答案 5 :(得分:1)

在这种情况下,

RequireJS非常有用。 您可以使用RequireJS声明JS文件的依赖关系。

您可以参考this简单教程。

答案 6 :(得分:1)

我认为最好的方法是使用RequireJS,如此处所提到的Does it make sense to use Require.js with Angular.js?这是完全允许的,它会让您达到您想要的目标。

这是一个示例代码

https://github.com/tnajdek/angular-requirejs-seed