• Angular项目构建指南


    如果你不知道什么是Angular或者根本没听说过,那么我接下来所说的对你来说毫无益处,不过如果你打算以后会接触Angular或者干脆要涨涨姿势~读下去还是有点用的.

        Angular和它之前所出现的其余前端框架最大的不同,在于它的核心不再是DOM,而是数据,是model.我们惯用的不管是单纯的jQuery还是MVC的Backbone,它们本质仍是让我们更方便更有条理的操作DOM,但是Angular不是.通过一系列魔术般的手法,它将一切的重心转移到数据上.以开发应用而不是操作节点的方式去开发Web,一切以数据为中心,数据的变化驱动了一切,包括行为.

        文本主题,如何构建一个angular项目?

        坦白说最开始构建一个项目的时候,虽然很小但是很纠结.我本身是有点完美主义的,所以虽然一开始什么都没有也想做到尽善尽美.因为听过很多前辈的经验,说如果框架基础没搭好,等到后来不管是重构还是维护都是一场噩梦.所以一开始小心意义,希望能将项目尽量搭建的结实并且益于维护和开发.

        在搭建伊始首先遇到的一个问题,就是到底要不要引入requirejs或者seajs这类依赖管理的工具?

        我本身没有多少语言或者技术的上的情节,对于各个大神也没有多少膜拜的憧憬(更多的是我根本不清楚谁是大神,也从没去找过).所以对于我来讲不管是requirejs的AMD还是seajs的CMD,从实现的角度上来讲都是做了同一个工作.在考虑一个Angular应用到底需不需要这种工具的时候,我也在网上看了很多人的说法.我总结一句就是,基本都和没说一样,也就是用不用随便,看情况.

        那么我能有什么好的答案,其实我现在的答案就是:"可以不用".怎么说是可以不用呢,如果你不用requirejs也能满足项目的开发以及各种需求,那么就别用了.angular本身的模块已经做到了依赖注入,所以我们不需要通过requirejs进行异步加载也可以很好的用下去.

        当然,如果你开发过程中发觉还是有些地方需要,那么也可以加上去.本文里我会详细说明这两种方式的构建方法.但是这里我的观点已经表明了:在不需要的情况下,不要用.

        (1) 不用requirejs直接构建Angular

        之所以不使用requirejs就直接构建angular,因为angular对于依赖的管理以及angular的使用场景完全可以做到这一点.首先在以来上,angular的依赖注入是个好东西,不了解的同学可以去搜一下资料.我这里简单的说,就是当我需要一个module的时候,我不用管它在哪,它是什么.我只要知道它的名字然后告诉angular就可以了,至于怎么将它的对象传递过来,怎么找到的,angular自己会去处理.

    1
    2
    3
    angular.module('myApp', [
      'ngRoute',
    ]);

        例如这里的ngRoute,我需要知道ngRoute怎么来的,在哪里.只要有一个模块定义为ngRoute我就可以直接拿来用.

        鉴于Angular如此的给力,剩下的事情就好办了.我们只需要从功能和业务两方面将文件划分成module就可以了,然后将所有的库文件在页面上通过script标签引用,再将所有的业务文件也即是我们自己写的js合并为一个all.js加载到页面上即可.

        这里文件的划分遵循angular官方的推荐方式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    |--js
       |--app.js                     // app启动文件,用于app配置
       |--controllers.js          // controllers也就是存放我们自己的业务文件
       |--directives.js            // 指令文件(指令可共用)
       |--fliters.js                  // 过滤器文件(过滤器可共用)
       |--services.js             //  服务文件(可共用,一般是与服务器交互的服务)
    |--partials
       |--html1.html  
       |--html2.html
    |--index.html

        app.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    'use strict';
     
     
    // Declare app level module which depends on filters, and services
    angular.module('myApp', [
      'ngRoute',
      'myApp.filters',
      'myApp.services',
      'myApp.directives',
      'myApp.controllers'
    ]).
    config(['$routeProvider'function($routeProvider) {
      $routeProvider.when('/view1', {templateUrl: 'partials/partial1.html', controller: 'MyCtrl1'});
      $routeProvider.when('/view2', {templateUrl: 'partials/partial2.html', controller: 'MyCtrl2'});
      $routeProvider.otherwise({redirectTo: '/view1'});
    }]);

        controllers.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    'use strict';
     
    /* Controllers */
     
    angular.module('myApp.controllers', [])
      .controller('MyCtrl1', ['$scope'function($scope) {
     
      }])
      .controller('MyCtrl2', ['$scope'function($scope) {
     
      }]);

        directives.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    'use strict';
     
    /* Directives */
     
     
    angular.module('myApp.directives', []).
      directive('appVersion', ['version'function(version) {
        return function(scope, elm, attrs) {
          elm.text(version);
        };
      }]);

        filters.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    'use strict';
     
    /* Filters */
     
    angular.module('myApp.filters', []).
      filter('interpolate', ['version'function(version) {
        return function(text) {
          return String(text).replace(/\%VERSION\%/mg, version);
        };
      }]);

        services.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    'use strict';
     
    /* Services */
     
     
    // Demonstrate how to register services
    // In this case it is a simple value service.
    angular.module('myApp.services', []).
      value('version''0.1');

        index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    <!DOCTYPE html>
    <!--[if lt IE 7]>      <html ng-app="myApp" class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
    <!--[if IE 7]>         <html ng-app="myApp" class="no-js lt-ie9 lt-ie8"> <![endif]-->
    <!--[if IE 8]>         <html ng-app="myApp" class="no-js lt-ie9"> <![endif]-->
    <!--[if gt IE 8]><!--> <html ng-app="myApp"> <!--<![endif]-->
    <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <title>My AngularJS App</title>
      <meta name="description" content="">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" href="bower_components/html5-boilerplate/css/normalize.css">
      <link rel="stylesheet" href="bower_components/html5-boilerplate/css/main.css">
      <link rel="stylesheet" href="css/app.css"/>
      <script src="bower_components/html5-boilerplate/js/vendor/modernizr-2.6.2.min.js"></script>
    </head>
    <body>
      <ul>
        <li><a href="#/view1">view1</a></li>
        <li><a href="#/view2">view2</a></li>
      </ul>
     
      <!--[if lt IE 7]>
          <p>You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
      <![endif]-->
     
      <div ng-view></div>
     
      <div>Angular seed app: v<span app-version></span></div>
     
      <!-- In production use:
      <script src="//ajax.googleapis.com/ajax/libs/angularjs/x.x.x/angular.min.js"></script>
      -->
      <script src="bower_components/angular/angular.js"></script>
      <script src="bower_components/angular-route/angular-route.js"></script>
      <script src="js/app.js"></script>
      <script src="js/services.js"></script>
      <script src="js/controllers.js"></script>
      <script src="js/filters.js"></script>
      <script src="js/directives.js"></script>
    </body>
    </html>

        如此在不使用requirejs的情景下,项目就构建完成了.还有几个补充点就是其一你可以将controllers继续拆分为多个controller模块,这里可以完全按照你的业务进行划分.比如user目录下userController等等.然后将所有这些我们自己写的文件通过grunt或者gulp进行合并为一个单独的总的文件all.js这样在页面中除了库文件只要这一个文件就行了.angular的module所带来的好处就是这样合并的文件,不用在乎js合并的顺序,因为它是通过angular依赖注入的.

        (2) 通过requirejs构建

        这种方式的构建可能对于某些人来讲更加清晰,结构和上面的基本一样,多了一个man.js用来配置requirejs,单独拆分出routes.js以及一个controller文件夹通过requirejs将controller一个个拆分出来,按需的异步加载.

        index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <!doctype html>
    <html ng-app>
    <head>
    <title>Angular-RequireJS sample app</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" media="all" href="app/css/app.css" />
    </head>
    <body >
    <h1>AngularJS + RequireJS</h1>
    <ul>
    <li><a href="#/view1">View 1</a></li>
    <li><a href="#/view2">View 2</a></li>
    </ul>
    <div ng-view></div>
    <script data-main="app/js/main" src="/bower_components/requirejs/require.js"></script>
    </body>
    </html>

        main.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    require.config({
        paths: {
            angular: '../../bower_components/angular/angular',
            angularRoute: '../../bower_components/angular-route/angular-route',
            angularMocks: '../../bower_components/angular-mocks/angular-mocks',
            text: '../../bower_components/requirejs-text/text'
        },
        shim: {
            'angular' : {'exports' 'angular'},
            'angularRoute': ['angular'],
            'angularMocks': {
                deps:['angular'],
                'exports':'angular.mock'
            }
        },
        priority: [
            "angular"
        ]
    });
     
    //http://code.angularjs.org/1.2.1/docs/guide/bootstrap#overview_deferred-bootstrap
    window.name = "NG_DEFER_BOOTSTRAP!";
     
    require( [
        'angular',
        'app',
        'routes'
    ], function(angular, app, routes) {
        'use strict';
        var $html = angular.element(document.getElementsByTagName('html')[0]);
     
        angular.element().ready(function() {
            angular.resumeBootstrap([app['name']]);
        });
    });

        app.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    define([
        'angular',
        'filters',
        'services',
        'directives',
        'controllers',
        'angularRoute',
        ], function (angular, filters, services, directives, controllers) {
            'use strict';
     
            // Declare app level module which depends on filters, and services
             
            return angular.module('myApp', [
                'ngRoute',
                'myApp.controllers',
                'myApp.filters',
                'myApp.services',
                'myApp.directives'
            ]);
    });

        controllers.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    define(['angular''services'], function (angular) {
        'use strict';
     
        /* Controllers */
         
        return angular.module('myApp.controllers', ['myApp.services'])
            // Sample controller where service is being used
            .controller('MyCtrl1', ['$scope''version'function ($scope, version) {
                $scope.scopedAppVersion = version;
            }])
            // More involved example where controller is required from an external file
            .controller('MyCtrl2', ['$scope''$injector'function($scope, $injector) {
                require(['controllers/myctrl2'], function(myctrl2) {
                    // injector method takes an array of modules as the first argument
                    // if you want your controller to be able to use components from
                    // any of your other modules, make sure you include it together with 'ng'
                    // Furthermore we need to pass on the $scope as it's unique to this controller
                    $injector.invoke(myctrl2, this, {'$scope': $scope});
                });
            }]);
    });

        directives.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    define(['angular''services'], function(angular, services) {
        'use strict';
     
      /* Directives */
     
        angular.module('myApp.directives', ['myApp.services'])
            .directive('appVersion', ['version'function(version) {
                return function(scope, elm, attrs) {
                    elm.text(version);
            };
        }]);
    });

        filters.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    define(['angular''services'], function (angular, services) {
        'use strict';
     
        /* Filters */
       
        angular.module('myApp.filters', ['myApp.services'])
            .filter('interpolate', ['version'function(version) {
                return function(text) {
                    return String(text).replace(/\%VERSION\%/mg, version);
                };
        }]);
    });

        routes.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    define(['angular''app'], function(angular, app) {
        'use strict';
     
        return app.config(['$routeProvider'function($routeProvider) {
            $routeProvider.when('/view1', {
                templateUrl: 'app/partials/partial1.html',
                controller: 'MyCtrl1'
            });
            $routeProvider.when('/view2', {
                templateUrl: 'app/partials/partial2.html',
                controller: 'MyCtrl2'
            });
            $routeProvider.otherwise({redirectTo: '/view1'});
        }]);
     
    });

        services.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    define(['angular'], function (angular) {
        'use strict';
         
      /* Services */
     
      // Demonstrate how to register services
      // In this case it is a simple value service.
        angular.module('myApp.services', [])
            .value('version''0.1');
    });

        controllers文件夹中一个单独controlle文件,myCtrl2.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    define([], function() {
        return ['$scope''$http'function($scope, $http) {
            // You can access the scope of the controller from here
            $scope.welcomeMessage = 'hey this is myctrl2.js!';
     
            // because this has happened asynchroneusly we've missed
            // Angular's initial call to $apply after the controller has been loaded
            // hence we need to explicityly call it at the end of our Controller constructor
            $scope.$apply();
        }];
    });

        结尾

        写到这应该差不多了,就快超字数了.通常情况下Angular应用的构建这样就可以了,因为比起传统框架angular的代码量上肯定会有优势,所以一些不必要的东西就不用引入了.上面这些也是我在这段时间的项目中遇到并且做过的,已经实战过了,所以如果有类似需求的同学可以不必在此填坑.

  • 相关阅读:
    [译]Angular-ui 之 多命名视图(Multiple Named Views)
    [译]Angular-ui 之 Url Routing
    解决错误:“废弃 document 元素之后的内容”——HTML5新特性,局部样式表
    调整iRedmail之Roundcube webmail服务不可不知的几件事
    iredmail邮件服务器之修改默认的web服务端口号
    CentOS6.5下安装iRedMail中需要解决的问题
    [转帖]CentOS下iRedMail安装配置
    基于HBase Hadoop 分布式集群环境下的MapReduce程序开发
    安装配置和使用HBASE Cluster(基于发行版CDH5.0.2)——系列随笔
    修改百度导航的配置文件,改变地图数据的存贮位置以解决空间不够的问题
  • 原文地址:https://www.cnblogs.com/GoodPingGe/p/4507722.html
Copyright © 2020-2023  润新知