3.2 AngularJS中的MVC

MVC是一种软件设计思想,并不是一门具体的技术,AngularJS框架中也引入了这种思想,下面就来看一下AngularJS中的MVC分别指的是什么。

● Model(模型):前面章节中提到过的作用域对象(例如$rootScope对象)中的属性。

● View(视图):大家所熟悉的DOM元素,从用户的角度来看就是HTML页面,在View中可以通过AngularJS表达式访问模型数据。

● Controller(控制器):用户自定义的构造方法,作用域中的模型数据可以通过依赖注入的方式注入控制器中。

注意

目前普遍认为AngularJS是一款MVW(Model-View-Whatever)框架,这是因为早期的AngularJS框架比较接近于MVC,而随着新版本代码的重构与API的改进,$scope对象可以认为是由一个方法(Controller)包装后的ViewModel,看上去更接近于MVVM(Model-View-ViewModel)框架,那么到底是MVC还是MVVM呢?不管怎样都行(Whatever),这就是MVW框架的由来。

3.2.1 AngularJS控制器的定义

AngularJS控制器是一个构造方法。有些JavaScript编程经验的朋友都知道,JavaScript方法可以作为对象模板实例化对象,当方法作为对象模板时,方法本身即为对象的构造方法。所以我们可以像定义一个普通方法一样定义一个控制器,例如:

        <script type="text/javascript">
            function LoginController($scope, $log){

            $scope.name="admin";
                $scope.pword="123456";
            }
        </script>

除此之外,我们还可以使用模块实例的controller()方法来声明一个控制器。该方法可接收两个参数,第一个参数为控制器名称,第二个参数为一个匿名方法,即控制器的构造方法,具体使用方法如下:

        <script type="text/javascript">
            var app =  angular.module("app", []);
            app.controller("LoginController", function($scope, $log){

            $scope.name="admin";

            $scope.pword="123456";
            });
        </script>

如上面的代码所示,AngularJS框架在window对象中增加了一个全局的angular对象,我们可以调用angular对象的module()方法返回一个模块实例,然后调用模块实例的controller()方法来声明一个控制器。这种方式最为常用,将会在后面的模块化章节中重点介绍。

在上面的案例代码中,我们定义控制器时指定了两个参数,即$scope和$log:$scope是作用域对象,是控制器与视图之间传递信息的载体;$log为AngularJS框架内置的日志服务对象,用于向控制台中输入日志信息。当我们为控制器构造方法指定这两个参数后,表示控制器依赖于这两个对象,控制器实例化时会把这两个对象注入控制器中。

注意

AngularJS 1.3版本之后已不再支持全局控制器,第一种控制器定义方式只适用于AngularJS 1.3之前的版本。

3.2.2 控制器对象的实例化

控制器对象的实例化非常简单,需要用到AngularJS内置的ng-controller指令。ng-controller的使用方法和ng-app指令类似,也是作为标签的扩展属性使用,具体如下:

        <div ng-controller="LoginController">
        </div>

AngularJS框架遇到ng-controller指令时会根据ng-controller指令指定的控制器名称查找控制器构造方法,然后使用对应的构造方法实例化控制器对象,并将控制器依赖的对象注入控制器对象中。

除此之外,ng-controller指令还支持使用as语法指定控制器对象名称,例如:

        <body ng-controller="CalcController as calc">
            <div>单价:<input type="number" ng-model="price" /></div><br/>
            <div>数量:<input type="number" ng-model="num" /></div><br/>
            <div>总价:{{calc.totalPrice()}}</div>
            <script type="text/javascript">
                function CalcController($scope){
                    $scope.price = 10;
                    $scope.num = 1;
                    this.totalPrice = function() {
                        return $scope.price * $scope.num;
                    }
                }
                var app = angular.module("app", []);
                app.controller("CalcController", CalcController);
            </script>
        </body>

如上面的代码所示,我们可以使用as语法指定控制器对象的名称为calc。这样做的好处是,可以通过控制器对象名称访问控制器对象的成员属性及成员方法。