07模块化-AngularJS基础教程

0. 目录

1. 前言

AngularJS是为了克服HTML在构建应用上的不足而设计的。HTML是一门很好的为静态文本展示设计的声明式语言,但要构建WEB应用的话它就显得乏力了,所以AngularJS做了一些工作来来解决静态网页技术在构建动态应用上的不足。

AngularJS的初衷是为了简化web APP开发,精髓是简单。但是国内外有很多AngularJS的教程,都着重讲AngularJS的强大之处,从而增加了AngularJS学习的难度,本教程试图用通俗的语言讲解最为基础最为实用的内容,简化学习进程、降低学习难度是本教程的初衷。

本系列教程以翻译Chris SmithAngualr Basics为梗概,融合博主自己的理解,为大家提供一个简单明了的学习教程。

本文为系列教程第7篇模块,翻译自Modules

  1. 引言-Introduction
  2. 基础-Basics
  3. 控制器-Controllers
  4. 作用域-Scopes
  5. 集合-Collections
  6. 模块-Modules
  7. 依赖注入-Dependency Injection
  8. 服务-Services
  9. 过滤器-Filters
  10. 指令-Directives
  11. 指令作用域-Directive Scopes
  12. 路由-Routing
  13. 通信-HTTP
  14. 结论

2.正文

总的来说,模块(modules)的目的是通过定义公共APIs、限制行为(功能)和数据(属性和变量)的可视化实现关注点分离(separation of concerns,soc)。大部分的编程平台内置了对模块化的支持,以致于我们会觉得理所当然而无所察觉。但是客户端javascript没有支持,对附加的解决方案(例如CommonJSAMD)的好处和坏处也进行了诸多争论。

需要注意的是,Angular的模块化系统不是模块化加载(它不从文件或internet加载源码),Angular提供的是内置的、私有的模块化方案工作原理类似于其内置的、私有的依赖注入方案,两个系统提供了令人印象深刻的通用基础设施。尽管使用模块化功能是每个开发者的需要掌握的内在能力,但问题是,为什么我们需要?

尽管模块化和依赖注入通常是必要命题,但是其实Angular允许我们不使用模块实现很多事情。截止目前,我们已经完成了一系列通过构造函数(在全局作用域定义和控制器一样名称的函数)不用模块的案例。通过一点简单的设置,ng-controller指令在全局范围和模块化系统中查找控制器函数,允许我们使用简化的方法使用Angular,但仅仅是一定程度上。

2.1 Why use Angular modules?(为什么使用模块化)

为了我们可以在Angular基础特性之后走的更远,我们需要精通它的模块化系统。相对于JS对象的管理复杂性问题来说,我们应该使用简单的方法解决问题,寻找您自己的最佳实践,因此本书不想详细介绍模块化和依赖注入的本质特性,只介绍跟Angular使用密切相关的模块和依赖注入的内容。

因此,让我们审视下必须使用Angular模块的重要特性:

  • 特殊组件-Specialized components,在定义您自己的控制器、指令、过滤器和动画的时候,我们必须使用模块系统(控制器可能例外,前面已经说过)
  • 依赖注入-Dependency injection,尽管服务是普通的JS对象和函数, 但使用模块系统创建的服务可以简单地被随着依赖性注入,进行依赖注入。
  • 外部模块-External modules,Angular拥有非常吸引人的开发社区,海量免费的官方插件、第三方插件,如果您要在您的应用中使用这些库,我们就不得不用到模块系统。
  • 加载时配置-Load-time configuration ,Angular的模块系统提供了访问内部配置、插件配置的功能,我们将在最后一章配置自定义HTTP头的案例中演示后面一个特性。
  • 测试-Testing, Angular令人心动的测试功能基于依赖注入实现,同样离不开模块系统

下一章我们讲服务,主要演示如何为自定义JS组件定义提供支持。本章讲解如何定义控制器加载外部模块,同时为您讲解模块系统的基础。

2.2 创建应用模块-Creating the application module

一个Angular应用通常起始于一个根模块,在我们的案例中这个模块名字叫做app,注意,这个名字虽说常见,很多时候就是简单起见,未必是最好的选择。

/* module.js */
angular.module(‘app‘, []);

在上面的案例中,需要特别注意module的第二个参数,尽管它看起来只是一个空的数组,但是它是非常重要的,如果您忽略它,angular.module的行为将产生根本改变。考虑到API的合理性设计, 当你指定第二个参数调用angular.module时,该方法处于创建模式,如果名为app的模块不存在,将创建一个名字为app的模块。但是调用angular.module时不指定第二个参数,它处于寻找模式,如果给定名称的模块存在将返回该模块,如果不存在将抛出错误,提醒我们注意第二个参数。该案例我们使用了正确的方式,但我们需要明白代码中的重要区别。这个参数用于导入外部模块,我们将会在angular动画模块时通过案例说明这一点。

2.3 加载应用模块-Loading the application module

在承载应用的HTML文档中,我们需要通过传递模块名称作为参数给ng-app指令告诉Angular加载应用模块。

<!-- index.html -->
<body ng-app="app">
  <!-- Other examples to be inserted here. -->
</body>

我们添加到应用模块中的任何组件都可以使用,让我们来看看如何使用模块定义一个控制器(不在使用全局的scope)。

2.4 定义控制器-Defining a controller

moduleAPI里面包含了定义特殊Angular组件的一些方法,截至目前我们比较熟悉的controller方法,我们使用controller方法创建控制器。首先我们需要取得一个应用模块的引用,同时我们需要给angular.module不指定第二个参数让它处于查询模式(主要是因为我们上文已经创建过应用模块了)。

/* message-controller.js */
var app = angular.module(‘app‘);
app.controller(‘MessageController‘, function($scope) {
  $scope.message = "This is a model.";
});

然后我们需要在调用ng-app的元素里面的某个位置,使用ng-controller调用我们的控制器。

<!-- message-controller.html -->
<p ng-controller="MessageController">
  {{message}}
</p>

编译结果为:This is a model.

您已经看到了,使用模块定义控制器比全局scope的方式稍微麻烦点,但不至于太糟。

2.5 链式定义-Chaining definitions

假设我们需要定义如下的两个控制器

<!-- another-message-controller.html -->
<p ng-controller="MessageController">
  {{message}}
</p>
<p ng-controller="AnotherMessageController">
  {{message}}
</p>

module的定义方法可以是链式操作,这样我们可以在一个语句里定义两个控制器。

/* chained-controllers.js */
angular.module(‘app‘)
  .controller(‘MessageController‘, function($scope) {
    $scope.message = "This is a model.";
  })
  .controller(‘AnotherMessageController‘, function($scope) {
    $scope.message = "This is another model.";
  });

编译结果为:
This is a model.
This is another model.

注意,第一个控制器的声明语句没有用分号结束。

如果你不喜欢链式操作风格,你可以随时检索调用模块,当然也可以存储在一个变量里(如下面代码所示)。如果您使用了变量,最好能够在IIFE(立即调用函数表达式)或者其他闭包里避免污染全局变量。

/* separate-controllers.js */
var app = angular.module(‘app‘);

app.controller(‘MessageController‘, function($scope) {
  $scope.message = "This is a model.";
});

app.controller(‘AnotherMessageController‘, function($scope) {
  $scope.message = "This is another model.";
});

选择哪种风格由您决定,不过链式风格更加流行些。

2.6 加载模块-Loading modules

Animation是Angular的一个新增特性,是一个名字叫做ngAnimate的独立模块。使用animations的第一步是引入包含模块,源文件中是Angular的核心部分,但是分发的时候以一个单独文件分发,如下所示。

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular-animate.js"></script>
<!-- 以上被墙,国内用另一个cdn -->
<script src="//cdn.bootcss.com/angular.js/1.3.14/angular.js"></script>
<script
src="//cdn.bootcss.com/angular.js/1.3.14//angular-animate.js"></script>

是时候我们使用module方法的第二个数组参数了,前面的案例我们只是传递了一个空参数, 这次我们声明模块的依赖性。

/* ng-animate-module.js */
angular.module(‘app‘, [‘ngAnimate‘]);

这样,我们在应用中引入了ngAnimate。 模板中的ng-show、ng-hide、ng-class等指令将会在css和js里检测JS animation,也许会应用在类似于add、enter、leave、move、remove等DOM事件中 。在DOM事件中应用animation无需模板做任何改变(感觉像透明一样), 如果动画代码没有呈现, 或者作为css或者作为js通过[module.animation](http://docs.angularjs.cn/api/ng/type/angular.Module)注册,指令代码还是普通代码。

<!-- ng-animate.html -->
<input type="checkbox" ng-model="showMessage">
Check the box to show the message
<h2 ng-show="showMessage">
  The secret message.
</h2>

编译结果为:
技术分享

单击上面的复选框,我们能够看到元素之间的显示与隐藏式立刻进行的,因为我们没有在css或js中添加动画。接下来,我们使用css(通过声明式风格创建一般动画的较好选择),当然使用jQuery的animate方法也不错,Angular的module.animation能够兼容这些方法。

控制淡入淡出需要四个额外的css类,ng-hide-add、ng-hide-add-active、ng-hide-remove、ng-hide-remove-active等。

/* ng-animate.css */
.ng-hide-add,
.ng-hide-remove {
  transition: all linear 1s;
  display: block !important;
}

.ng-hide-add.ng-hide-add-active,
.ng-hide-remove {
  opacity: 0;
}

.ng-hide-add,
.ng-hide-remove.ng-hide-remove-active {
  opacity: 1;
}

这次的编译结果如下所示。
技术分享

Depending on your site’s users, you may need to add vendor-prefixed properties for certain browsers, such as -webkit-transition for iOS Safari 6. (The site caniuse.com is a good reference for browser compatibility with HTML5 and CSS3.) Please also note that as written, this animation will applied to every usage of ng-show and ng-hide in our application. For better control, we can add a custom CSS class to both the element and the CSS selectors, for example .my-class.ng-hide-add, .my-class.ng-hide-remove, and so on.
根据您的网站的用户需要,你可能需要给特定的css属性增加浏览器引擎前缀(vendor-prefix),例如针对iOS Safari6增加-webkit-transition(caniuse.com是一个比较好的html5、css3浏览器兼容性网站)。注意这个动画将附加到任何一次ng-show、ng-hide使用中,为了做更好的控制,我们可以在元素和选择器上增加自定义css类,例如.my-class.ng-hide-add.my-class.ng-hide-remove等等。

2.10 结论

添加ngAnimate的案例我想让您确信理解Angular 模块系统的重要性。而且,令人高兴的是,ngAnimate只是使用Angular附件模块的开始,除了可以使用官方提供的模块资源外,大家还可以到github之类的网站上寻找更多的第三方开源模块。最流行的一个项目是AngularUI,提供了UI Router、UI Bootstrap等强大的模块,这些模块可以方便地使用Bower进行安装,当您上手Angular之后,您也可以在Github和Bower发布您的Angular模块,等你哟!

ngAnimate模块演示一个如何使用附件模块发挥强大功能的案例,但是因为它特殊的嵌入方式,没有使用依赖注入。因为模块和依赖注入需要相互协作,下一章我们将讲解依赖注入。

3.声明

前端开发whqet,关注前端开发,分享相关资源。csdn专家博客,王海庆希望能对您有所帮助,限于作者水平有限,出错难免,欢迎拍砖!
欢迎任何形式的转载,烦请注明装载,保留本段文字。
本文原文链接,http://blog.csdn.net/whqet/article/details/45074873
欢迎大家访问独立博客http://whqet.github.io

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。