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