4.2 AngularJS中的模块

在前面的几章中,由于代码比较少,为了方便说明问题直接把控制器代码写在了HTML页面中,这样会使代码的可维护性差,实际项目中并不会这么做。通常的做法是把处理业务逻辑的代码写在单独的JS文件中,然后在HTML页面中引入该文件。

然而这样会带来新问题:在AngularJS 1.3版本之前是支持全局控制器的,如果我们的控制器全都定义在全局命名空间中,假设有一个公共的JS文件在多个页面同时引用,并且同一个项目由多人协作完成,不同开发人员在同一个文件中新增控制器或者服务的定义就容易造成命名冲突。AngularJS应用的模块划分就能够很好地解决这个问题。

4.2.1 AngularJS模块的定义

前面章节中提到过,AngularJS框架在window对象下新增了一个全局的angular对象,我们可以调用angular对象的module()方法返回一个模块实例,具体使用方法如下:

        //定义一个无依赖模块
        angular.module('appModule', []);
        //定义一个依赖module1、module2的模块
        angular.module('appModule', ['module1', 'module2']);

angular.module()方法能够接收3个参数。第一个参数为模块的名称。第二个参数是一个数组,用于指定该模块依赖的模块名称。如果我们的模块不需要依赖其他模块,第二个参数传递一个空数组即可。第三个参数为可选参数,该参数接收一个方法,用于对模块进行配置,作用和模块实例的config()方法相同。

angular.module()方法返回一个模块实例对象,我们可以调用该对象的controller()、directive()、filter()等方法向模块中添加控制器、指令、过滤器等其他组件。

模块定义完毕后,如何在HTML页面中引用呢?其实很简单,在使用ng-app指令时指定模块名即可,例如:

        <html ng-app="appModule">

上面代码中的appModule为调用angular.module()方法时指定的模块名称。

4.2.2 使用模块解决命名冲突问题

上一小节介绍了模块的定义,本小节以一个实际的案例说明如何使用模块解决命名冲突问题。假设我们有两个HTML页面,分别为注册页面和登录页面,在两个页面中引入一个公共的common.js文件,我们把控制器的定义放在common.js文件中,当两个页面定义的控制器名称相同时就会产生命名冲突。我们来看一下AngularJS是如何使用模块来解决命名冲突的。

首先是登录页面,具体内容如下:

代码清单:ch04\ch04_1\login.html

        <!doctype html>
        <html ng-app="loginModule">
        <head>
            <meta charset="UTF-8">
            <title>登录页面</title>
            <script src="/angular-1.5.5/angular.js"></script>
            <script src="common.js"></script>
        </head>
        <body>

            <div ng-controller="UserController">
                <div>用户名:<input type="text" ng-model="uname" placeholder="用户名"/>
                </div><br/>
                <div>密  码:<input type="password" ng-model="pword" placeholder="密码"/>
                </div><br/>
                <div><button ng-click="submit()">登录</button></div>
            </div>
        </body>
        </html>

如上面的代码所示,登录页面要素非常简单,只有两个输入框和一个按钮,在login.html页面使用ng-controller实例化名称为UserController控制器,该控制器在common.js文件中定义。接下来是注册页面,具体内容如下:

代码清单:ch04\ch04_1\register.html

        <!doctype html>
        <html ng-app="registerModule">
        <head>
            <meta charset="UTF-8">
            <title>注册页面</title>
            <script src="/angular-1.5.5/angular.js"></script>
            <script src="common.js"></script>
        </head>
        <body>
            <div ng-controller="UserController">
                <div>用户名:<input type="text" ng-model="uname" placeholder="用户
                名"/>
                </div><br/>
                <div>密  码:<input type="password" ng-model="pword" placeholder="
                密码"/>
                </div><br/>
                <div><button ng-click="submit()">注册</button></div>
            </div>
        </body>
        </html>

如上面的代码所示,注册页面元素和登录页面类似,我们在该页面中也通过ng-controller控制器实例化名称为UserController的控制器,也是在common.js文件中定义,但是我们希望登录页面和注册页面使用不同的控制器进行业务逻辑处理,该怎么办呢?

我们可以在common.js文件中使用AngularJS模块来对这两个控制器进行划分,代码如下:

代码清单:ch04\ch04_1\common.js

        var loginModule = angular.module("loginModule", []);
        loginModule.controller("UserController", function($scope, $log){

            $scope.uname = "login";
            $scope.pword = "admin";
            $scope.submit = function() {
                alert("登录模块:UserController");
            }
        }                                    )                                    ;

        var registerModule = angular.module("registerModule", []);

        registerModule.controller("UserController", function($scope, $log){
            $scope.uname = "register";
            $scope.pword = "admin";
            $scope.submit = function() {
                alert("注册模块:UserController");
            }
        });

如上面的代码所示,我们调用angular.module()方法创建了两个模块实例,名称分别为loginModule和registerModule,然后分别调用这两个模块实例的controller()方法创建两个名称均为UserController的控制器,这两个控制器属于不同的模块,在login.html页面中使用ng-app="loginModule"指定页面使用loginModule模块中的内容,而在register.html页面中使用ng-app="registerModule"指定使用registerModule模块中的内容。

在浏览器中运行ch04\ch04_1\login.html页面,如图4.1所示。单击“登录”按钮,提示“登录模块:UserController”,说明该页面使用的是loginModule模块下的UserController控制器。

接着运行ch04\ch04_1\register.html页面,如图4.2所示。单击“注册”按钮,提示“注册模块:UserController”,说明该页面使用的是registerModule模块下的UserController控制器。

图4.1 登录页面预览效果

图4.2 注册页面预览效果