上一篇:【译】《精通使用AngularJS开发Web App》(一)
下一篇:【译】《精通使用AngularJS开发Web App》(三)
原版书名:Mastering Web Application Development with AngularJS
Chapter 1
AngularJS速览
现在我们已经知道了到哪儿去找框架的源码,以及相关的文档,现在我们就可以开始编码了,在实战中看看AngularJS究竟是什么样子的。
本书的这一部分将为随后的章节打下基础,会涵盖 AngularJS模板,模块化,和依赖注入。任何的AngularJS web app 都是由这些基础组建而成的。
Hello World - AngularJS示例
我们对AngularJS的第一印象就用典型的 Hello, World!
来演示,看看用AngularJS是如何来写的,同时也看看它所使用的语法。
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/
angular.js"></script>
</head>
<body ng-app ng-init="name='World'">
<h1>Hello, {{name}}</h1>
</body>
</html>
首先需要引入AngularJS,这样才能在浏览器中正确运行。这就像AngularJS一样简单,它最简单的形式就是引用一个javascript文件。
AngularJS 相对来说还是比较小的:压缩并gzip之后大概只有30KB,压缩不gzip的话大概有80KB。它并不依赖任何第三方类库。
本书的小例子中我们会使用未经压缩的,开发友好的版本,在Google的CDN上。同时AngularJS的所有版本都可以在这里下载到:http://code.angularjs.org
在实际运行中,仅仅把AngularJS包含进来还不够,我们还需要启动这个小应用。最简单的方式就是使用自定义的属性 ng-app
。
<body>
标签附近可以看到另一个非标准的 HTML 属性:ng-init
。我们可以使用 ng-init
在模板被渲染之前来初始化模型。最后要说到的就是 {{name}}
表达式,它就是简单的把模型的值给渲染出来了而已。
即便是在这最开始的、最简单的小例子中,也可以看到AngularJS模板系统的一些重要特性,如下所示:
- 自定义的 HTML 标签和属性可以给本来是静态的 HTML 文档增添动态行为。
- 两个花括号({{expression}}
)是一个用来输出模型值的表达式的定界符。
在 AngularJS 中,所有的可以被框架所理解和解析的特殊的 HTML 标签和属性都是指令(directive
)。
双向数据绑定
对 AngularJS 来说,渲染模板简直就是最拿手的工作了;特别是当要构建一个动态web 应用的时候,AngularJS简直就能发光升仙了。为了让咱们能欣赏到 AngularJS 的真正的力量,我们就用 input
来扩展一下之前的 Hello World
,如下所示:
<body ng-app ng-init="name='World'">
Say hello to: <input type="text" ng-model="name">
<h1>Hello, {{name}}</h1>
</body>
这个 input
标签处了额外的 ng-model
之外简直就毫无特别之处。真正的魔法力量将会在我们在input
中输入文字的时候展现。突然之间,屏幕会在每次键盘敲击之后进行重绘,显示出你所敲打的名字!要刷新一个模板,你并不需要编写任何一行代码,我们也没有被强迫调用任何一个框架的 API 来更新数据模型。AngularJS 是足够聪明的,可以自动检测到模型的变化并相应的更新DOM。
大多数的传统的模板系统渲染模板时都是线性的,单向的:模型(变量)和模板被拼合在一起并将计算的结果输出。模型的任何改变都需要模板的重新计算。AngularJS无需如此,因为任何的用户引起的视图变化,都会立即映射到对应的模型中,同时,任何模型的变化也会马上传播到模板中去。
AngularJS中的MVC
大部分现存的web应用都是构建在知名的 模型-视图-控制器(MVC) 模式的某种形式之上。但是 MVC 最大的问题在于,它本身并不是一个非常清晰的模式,而是很高阶很结构化的。更糟糕的是,最原始的模式又变异、衍生出很多种模式(最知名的可能是 MVP 和 MVVM)。要加入这些混乱的、不同的框架,开发人员常常会对这些模式做出不同的理解和解释。这样的结果就是,用着相同的 MVC 的名号,却在描述一个不同的架构和编码实现。Martin Fowler 在他很优秀的关于GUI架构的文章中对此有很好的总结(http://martinfowler.com/eaaDev/uiArchs.html)。
就拿 模型-视图-控制器 来说,它经常被拿来当作一个模式来说事,但我却不觉得把它当做一个模式是个什么好事,因为它本身包含了很多不同的思路。不同的人看到 MVC 不同的地方会得出不同的结论,并成他们的理解为 "MVC"。如果这还没有造成足够的混乱,那你终将会从 根据对 MVC 的误解而开发的像 Chinese whispers(一个耳语传话的游戏,详见这里) 一样的系统 中看到最后的效果。
AngularJS团队本着非常务实的态度来整个MVC模式家族,并宣称这个框架是基于MVW(模型-视图-随便你是啥)模式的。一般说来只有在实践中见识到来能感受到(究竟如何)。
鸟瞰
我们到现在为止所见到的 Hello World
都还没有使用任何的分层策略:数据初始化,逻辑,还有视图都混在一个文件之中。在任何实际的应用中,我们都需要把更多的注意力放在分配给每层的那些责任上面。幸运的是,AngularJS提供了一些不同的构建方式,可以正确地构建更加复杂的应用。
本书后面的例子都会省略掉 AngularJS 的初始化代码(引入脚本,ng-app 属性,等等),这样更利于阅读。
我们一起来看看这个稍微修改过的 Hello World
:
<div ng-controller="HelloCtrl">
Say hello to: <input type="text" ng-model="name"><br>
<h1>Hello, {{name}}!</h1>
</div>
ng-init
属性被移除了,然后我们增加了一个新的 ng-controller
指令,以及对应着一个 JavaScript 函数。这个 HelloCtrl
还接受一个相当神秘的 $scope
作为参数:
var HelloCtrl = function ($scope) {
$scope.name = 'World';
}
Scope(作用域)
AngularJS中的 $scope
对象在这里就是要将 域模型 暴露给视图(模板)。只需把属性设置给 scope 实例,就可以在模板渲染时得到这个值。
Scopes(作用域)也可以针对特定的视图来扩展数据和特定的功能。只要在 scope
实例上定义一些函数就能将特定的 UI 逻辑暴露给模板了。
例如,你可以给 name
变量创建一个 getter 方法,如下所示:
var HelloCtrl = function ($scope) {
$scope.getName = function() {
return $scope.name;
};
}
然后就像下面这样在模板中使用:
<h1>Hello, {{getName()}} !</h1>
$scope
对象让我们可以非常精确的控制这个域内的模型的哪一部分,以及哪些操作在视图层是可用的。理论上来讲,AngularJS的 scopes 非常类似于 MVVM 模式的 ViewModel。
控制器
控制器的首要任务就是初始化scope对象。在实践中,初始化的逻辑由下面的这些责任组成:
- 提供模型初始化的值
- 扩展 $scope
的 UI 行为(方法)
控制器都是普通的 JavaScript 函数。他们并不必去继承一些框架特定提供的类,也不必去调用任何特定的 AngularJS API才能去正确的执行他们的任务。
请注意,控制器在设置模型的初始值时是跟
ng-init
指令所做的任务一样的。有了控制器,才使得使用 JavaScript 来表达初始化的逻辑成为可能,而不必拿代码把HTML模版搞的一团糟。
模型
AngularJS 的模型就是那些普通的 JavaScript 对象。我们不必被强迫去继承一些框架的基础类,也不必以某种特殊的方式来初始化模型对象。
使用任何现有的,纯JavaScript类或对象,就跟在模型层一样的去使用它们也是可以的。同时也没有被限制说只能使用最原始的值来做模型属性(任何合法的JavaScript 对象或数组都可以使用)。要把模型暴露给 AngularJS,你只需把它赋值给 $scope
的属性即可。
AngularJS不是侵入式的,所以可以放心的把任何针对其他框架特定的代码拿来当作模型使用。
转载请注明来自[超2真人]
本文链接:http://www.peichao01.com/static_content/doc/html/Mastering_Web_Application_Development_with_AngularJS_2.html
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。