上一篇:【译】《精通使用AngularJS开发Web App》(三)
下一篇:javascript
书名:Mastering Web Application Development with AngularJShtml
Chapter 1java
咱们已经见了这许多AngularJS模版的例子,应该认识到他并非“又出现一个模板语言”,但确实仍是有许多的不一样(跟其余模板语言相比)。不只是说框架的模板语法依赖于HTML,还容许咱们来扩展HTML的词汇,并且还有能够在没有任何人工干预的状况下刷新局部视图这种的独一无二的能力!数据库
事实上,AngularJS 与 HTML 和 DOM 的联系更为密切,由于它就是依赖浏览器来解析模版内容的(就跟浏览器会对任何其余的HTML文档所作的那样)。在浏览器把标记文本转化为 DOM 树以后,AngularJS就会进入这个解析好的DOM结构。而后,每当遇到一个指令,AngularJS就会执行它的逻辑,并将指令变为动态的内容。编程
既然AngularJS 依赖于浏览器来解析模板,咱们就须要确保提供的模板是合格的HTML内容。要特别注意HTML标签的正确闭合(不然的话,不会输出错误信息,但视图却不会被正确的渲染出来)。AngularJS 必须在正确的DOM树上工做。segmentfault
AngularJS 使得丰富HTML的词汇表成为可能(咱们能够添加新的属性或HTML元素,并教会浏览器应该如何解析他们)。这就像在 HTML 基础上建立一门特定领域语言(domain-specific language
),并指导浏览器如何理解新的指令。你可能常常会听到AngularJS“教了浏览器一些新的技巧”。浏览器
AngularJS自带了不少方便的指令,咱们将会在后面的章节中涵盖其中的大部分。最重要的事情,其实不是去了解单个指令的语法和功能,而是 AnulgarJS 构建 UI 的背后的哲学思想。app
AngularJS 推广了一套声明式的构建 UI 的方式。在实践中这意味着,模板会把重心放在如何描述一个指望的效果,而不是如何具体实现它。听起来可能有点困惑,那就看个例子吧。框架
让咱们想象一下这种状况,咱们须要建立一个form,用户能够输入一些简短的文字,而后能够点击按钮发送表单。固然这还涉及到一些用户体验的事情,好比文字长度须要限制在100字之内,若是超出范围就禁用 发送 按钮。用户须要在他们输入的时候知道还剩多少个字。若是剩余的字数小于10,那么提示文字就要改变样式为警告的状态。也须要可以清除已经存在的文字。完成后的form可能看起来以下图:
上面这个需求不是特别有挑战性,也只是一个普通的文本表单,尽管如此,这里仍是因为多须要整合的UI元素,好比,要确保按钮的 disabled
禁用状态能够正常工做,剩余字数要用恰当的样式来准确的显示等等。首次尝试的实现代码以下:dom
<div class="container" ng-controller="TextAreaWithLimitCtrl"> <div class="row"> <textarea ng-model="message">{{message}}</textarea> </div> <div class="row"> <button ng-click="send()">Send</button> <button ng-click="clear()">Clear</button> </div> </div>
咱们仍是使用前面的代码做为起点,在那个基础上继续。首先,咱们须要显示剩余字数,这个至关容易,以下所示:
<span>Remaining: {{remaining()}}</span>
remaining()
函数定义在 TextAreaWithLimitCtrl
控制器中的 $scope
上,以下:
$scope.remaining = function () { return MAX_LEN - $scope.message.length; };
而后,咱们须要在文本不符合字数限制的时候禁用 Send
按钮。这个能够用 ng-disabled
指令很容易的实现,以下:
<button ng-disabled="!hasValidLength()"...>Send</button>
这里使用了一个固定模式。要操做UI的话,只需接触模板的一小部分,而后根据模型的状态(这里就是文本的长度)描述一个指望的输出结果(显示剩余字数,禁用按钮等)便可。最有意思的地方在于,咱们不需在 JavaScript 代码中持有任何对DOM元素的引用,咱们也不须要准确的操控DOM元素。如今咱们只需关注模型的变化,让 AngularJS 去作那些枯燥繁重的工做去吧。咱们所须要作的只是在这种形式的指令中提供一些建议。
继续回到咱们的例子中来,咱们还要确保剩余字数的提示要在只剩下不多字数的时候改变样式。这是一个能够可实战中学习另外一个声明式UI的例子的好机会。以下所示:
<span ng-class="{'text-warning' : shouldWarn()}"> Remaining: {{remaining()}} </span>
shouldWarn()
方法的实现以下所示:
$scope.shouldWarn = function () { return $scope.remaining() < WARN_THRESHOLD; };
CSS class 的变化是根据模型的变化而来的,可是咱们并无在 JavaScript 中写任何的操做 DOM 的代码!UI 会基于以声明的方式表达的“想要干吗”而重绘。咱们用 ng-class
指令所表达的意思是:“每次字数超出限制,都要经过把 text-warning
加到 <span>
元素的 class 上面 来给用户一个警示”。这跟下面这种说法是至关不一样的 “当输入一个新的字符,而且字数超出了限制,就去找到 <span>
元素,而后改变这个元素的 CSS class text-warning
”。(译注:两种不一样的思路,前一种是描述你所但愿的状态,后一种是彻底的把你要实现这种结果的过程描述出来)。
咱们这里说的好像只是有点微妙的不一样,但其实,声明式的和命令式的是两种至关对立的实现方式。命令式的编程,重点在于描述每个单独的过程,并将结果导向但愿获得的结果。声明式的方式,重点在于但愿获得的结果。至于要达到这个结果的那些独立的步骤是由支持这种方式的框架所关心的。这就像是在说“亲爱的 AngularJS,这就是当模型到某个状态以后,我所但愿的UI可以展现的状态,如今呢,就请开始想一想何时以及如何来重绘这些UI吧”。
声明式的编程一般更富有表达力,由于把开发人员从很是细微的、底层的指令(编码)中解放出来了。产出的代码一般都很是的简洁、易于阅读。但若要在工做中使用声明的方式,就必须有装备工具可以正确的理解更高级的指令。咱们的程序开始依赖于这些机器的决定,而且咱们须要放弃一些底层的控制权。使用命令式的方式,咱们拥有彻底的控制权,也能很好的协调好每个单独的操做。咱们获得了更多的控制权,这种“负责任”的代价就是要写很是多的底层的、重复的代码。
熟悉 SQL 语言的读者会以为这些听起来都很是的熟悉(SQL 是一个针对请求临时(adhoc)数据的很是富有表达力的声明式的语言)。咱们简单的描述一下须要获得的结果(去fetch的数据),以后的就是去让(关系型)数据库去想该怎么去拿到特定的数据了。绝大多数状况下,这个过程都能完美的工做,咱们也能很快速的拿到咱们所想获得的。固然也有一些状况须要给出更多的提示(索引(indexes),查询计划提示(query planner hints)等等),或者手动控制数据检索过程,以便优化性能。
AngularJS模板中的指令声明式的描述了所指望的结果,因此呢,咱们得以从一步步的给出若是改变DOM元素的各个属性(基于 jQuery 的应用一般须要如此)中解脱出来。AngularJS 极力推广在模板上使用声明式的编程,而在javascript代码中是用命令式的(控制器和业务逻辑)。使用 AngularJS的话,咱们不多会使用到低级的、命令式的指令来操做DOM(惟一的例外是在指令里面中的代码)。
就经验而言,千万不要在 AngularJS控制器中操做 DOM 元素。在控制器中获取一个DOM的引用,并操做DOM的属性,是在用命令式的方式控制UI -- 这是跟 AugularJS 构建 UI 的思想相悖的。
使用 AngularJS 指令写出来的声明式的 UI 模板能够很迅速的描述出复杂的、交互的UI。AngularJS 会自主作出全部这些底层决定什么时候以及如何操做DOM树的部分。绝大多数时候 AngularJS 会作出“正确的事情”,并更新UI为所预期的(也很是及时的)。不过,理解 AngularJS 的内部工做原理也很是的重要,这样的话咱们就能够在须要的时候给框架一些适当的提示。这里的状况跟 SQL 又很是的类似,大多数状况下,咱们都不须要为查询计划的工做状况操心。但当咱们遇到性能问题的时候,了解查询计划是如何下决定的就很是有价值了,这样一来咱们就能够给它提供更多的意见。这一样适用于 AngularJS 的UI 管理:咱们须要了解背后的机制,以便于更高效的使用模板和指令。
细心的读者可能已经发现了,到目前为止所用到的例子都是使用的全局的构造函数来定义控制器的。可是,全局的状态是邪恶的,它危及了应用的结构,让代码更难以维护,测试,和阅读。AngularJS 毫不会建议使用全局状态的。相反,它提供了一整套的 API,能够很方便的定义模块,在这些模块中注册对象。
我么一块儿来看看怎么把一个丑陋的,全局定义的控制器转换为同等的模块化的定义。以前的控制器是这么声明的:
var HelloCtrl = function ($scope) { $scope.name = 'World'; }
模块化以后是这样的:
angular.module('hello', []) .controller('HelloCtrl', function($scope){ $scope.name = 'World'; });
AngularJS 自身定义了一个全局的 angular
名字空间。这个名字空间提供了不少不一样类型的工具和方便的方法,module
就是这些方法的其中一个。module
会扮演一个其余的AngularJS须要管理的对象(控制器、服务等)的容器。正如咱们以后就会看到的,除了简单的名称空间和代码组织以外,模块还有很是多的东西须要学习。
要定义一个新的模块,咱们须要给 module
方法的第一个参数提供模块的名字。第二个参数指定所须要依赖的模块(在以前的模块中,咱们没有依赖与任何其余模块)。
对 angular.module
方法的调用会返回一个新建立的模块的实例。一旦咱们是用这个实例,就能够开始定义新的控制器了。这很是的简单,只需使用以下参数来调用 controller
便可:
- 控制器的名字(字符串类型)
- 控制器的构造函数
全局定义的控制器构造函数只适用于快速示例和原型开发。永远不要在大型的、真实的应用中使用全局定义的控制器。
如今已经定义了一个模块,但咱们还须要通知 AngularJS 它的存在。这是经过给 ng-app
属性提供一个值来完成的,以下:
<body ng-app="hello">
一个常常犯的错误就是忘记了在
ng-app
属性中指定模块的名字,这也会形成一些常见的困惑。在ng-app
属性中省略模块名称会引发错误,说明有未定义的控制器。
转载请注明来自[超2真人]
本文连接:http://www.peichao01.com/static_content/doc/html/Mastering_Web_Application_Development_with_AngularJS_4.html