构建移动网站与APP:ionic移动开发入门与实战 (跨平台移动开发丛书)
上QQ阅读APP看书,第一时间看更新

3.2 代码模块与依赖注入

在图3.1的AngularJS应用的概要组件图中没有出现模块的字样,然而这不代表它没出现在图里。实际上图中的指令、服务(句柄)、控制器都是定义在AngularJS的模块里。读者从图3.3展现的图中可以看到所有类型的AngularJS组件都是归属于作为容器的某个模块的。

图3.3 AngularJS模块与组件定义关系

自然地,如果要会使用AngularJS,就需要解决两个问题:如何在模块里创建组件以及如何使用其他模块里的组件。下文的3.2.1和3.2.2节将分别回答这两个问题。

3.2.1 定义模块与组件

定义AngularJS模块的代码格式比较固定,为以下形式:

        var _module = angular.module(moduleName, importedModulesArray);

其中moduleName是字符串类型的模块名,importedModulesArray代表需要被本模块所导入的其他模块名,由字符串数组组成,如果没有需要导入的其他模块,也需要传入一个空数组。返回值为被定义出来的模块对象。

在完成了AngularJS模块的定义后,也可以通过如下方式调用来获得模块对象:

        var _module = angular.module(moduleName);

其中moduleName是字符串类型的模块名。

而定义组件是通过调用上一步骤获得的模块对象的组件工厂方法完成,形式如:

        _module.controller(componentName,        ["otherComponentName1",        …        ,
    "otherComponentNameN", function(otherComponentName1, … , otherComponentNameN){
        ……//业务逻辑代码
        }]);

其中的controller可以根据需要定义的组件类型而更换成filter、service等图3.3中出现的类型英文名称。componentName是字符串类型的组件名,该组件需要依赖使用的其他组件otherComponentName1…otherComponentNameN按以上格式依序使用字符串作为参数传入,而真正的模块对象定义函数再依序将其依赖使用的其他组件作为函数参数的一部分。

提示

此处两次列举出依赖使用的其他组件列表的形式是为了避免JavaScript代码混淆器造成的副作用而使用的,具体的原因读者可以自行参考网上相关的介绍文章,此处不再赘述。

把两个步骤合在一起,就可以写出类似下面示例3-1的代码片段了。

【示例3-1】演示了定义名为myApp的模块并在myApp模块内动态定义名为myCtrl的控制器组件。

        //定义名为myApp的模块
        var app = angular.module("myApp", ["ionic"]);

        //在myApp模块内动态构建名为myCtrl的控制器组件
        app.controller("myCtrl", ["$rootScope", function($rootScope) {
          //设置一个数据模型上的属性
      $rootScope.appName = "IonicAPP";
      //设置一个数据模型上的方法
      $rootScope.sayAppName = function(){
        console.log($rootScope.appName);
      };
        }]);

【代码解析】定义名为myApp的模块的时候,第二个["ionic"]代表模块需要引入使用名为ionic模块。(此处仅为演示目的引入,示例里并没有使用Ionic的组件)随后通过对myApp的模块实例app的controller方法调用,定义了名为myCtrl的控制器。该控制器依赖于AngularJS内置的$rootScope服务组件。在控制器的内部,利用$rootScope组件分别定义了数据模型上最顶层的根作用域对象的appName属性和sayAppName方法。

3.2.2 使用模块与组件依赖注入

使用模块与组件就相对容易了,在示例3-1中,定义名为myApp的模块的时候,就通过最后的参数["ionic"]代表myApp模块需要引入使用名为ionic的模块。如果还需要引入其他模块,则在数组里使用同样格式增加其他模块名即可。

组件依赖注入也同样体现在了示例3-1中。由于myCtrl控制器组件需要(依赖)$rootScope的服务,因此这里把作为AngularJS内置的$rootScope服务组件通过指定的格式放入了myCtrl控制器组件的定义函数签名中。AngularJS的注入服务将自动处理定位$rootScope服务组件并获取其处于缓存中的句柄,在myCtrl控制器组件被创建时以函数参数方式注入。

3.2.3 AngularJS模块与JavaScript文件

AngularJS的开发小组推荐了一个基于AngularJS的应用的基于模块类别的切分方案,而Ionic CLI生成的项目模板基本也是遵照这个方案,如图3.4所示。

图3.4 AngularJS应用基于模块类别的切分方案

一般是图3.4中的第二层的每个组件类型方框分别实现到一个JavaScript文件中,并为每个组件类型单独建立一个模块。而顶部的app应用模块也作为入口点文件,声明对其他模块的引用依赖。