天天看点

《AngularJS深度剖析与最佳实践》一 2.4 控制器

本节书摘来自华章出版社《angularjs深度剖析与最佳实践》一书中的第2章,第2.4节,作者 雪狼 破狼 彭洪伟,更多章节内容可以访问云栖社区“华章计算机”公众号查看

和传统的mvc程序中一样,angular中的控制器(controller)用来对模块(scope)进行操作,包括初始化数据和定义事件响应函数等。

我们常见的定义控制器的方法是:angular.module('com.ngnice.app').controller ('userlistctrl', function() {...});,其中:angular.module('com.ngnice.app')语句在前面已经讲过,是返回一个现有的module实例,而controller就是这个module实例上的一个方法,它的作用是把后面的函数以userlistctrl为名字,注册到模块中去,以便需要时可以根据名字找到它。

使用控制器的场景有几种。最常见的是用在路由中。

比如在angular-ui-router中,我们可以通过下面的语句使用它:

这样,当用户访问/user/list这个url的时候,angular-ui-router插件就会实例化一个名为userlistctrl的控制器,同时,创建一个scope对象并传给它。这个控制器实例会在这个scope对象上创建属性、方法等,这个过程称为“初始化scope对象”。

初始化完之后,加载模板,并且把scope对象传入,模板中会通过angular指令绑定这些属性、方法。angular会通过一个称为摘要循环(digest cycle)的过程,自动维护scope变量和视图中dom节点的一致性,这时候的dom我们称之为“活dom(live dom)”。更具体的工作原理我们会在第3章“背后的原理”的3.2节“angular启动过程”中详细讲解。

另一个常用的场景是在单元测试中。

通常,在单元测试阶段我们不必测试视图,而是将其留待端到端测试阶段。在单元测试阶段,我们要关注的是控制器的工作逻辑。前面我们提过,控制器的作用是在scope对象上创建属性、方法,所以我们的测试逻辑就是看它是否创建了正确的属性,以及由它创建的方法是否能正常工作。

于是我们得出了下列测试逻辑:

其中的$controller是angular提供的一个系统服务,用来查找以前通过module.controller('userlistctrl', function() {...});注册的控制器函数。

还有一个不常用但值得提倡的场景是在指令中,特别是用来封装一个界面片段的“组件型指令”,我们在2.6节“指令”中会进一步展开讲解。之所以在这种类型的指令中提倡使用控制器,主要是为了方便进行单元测试,而不用引入对视图层的测试。

有一些第三方服务或指令也会使用控制器,它们所做的工作实际上和angular-ui-router一样的:创建一个scope,找到一个控制器,然后用控制器对scope进行初始化,最后把scope绑定到视图,把生成的live dom渲染出来。

掌握了控制器的工作原理,在自己的代码中也可以灵活运用,凡是需要live dom的地方都可以通过各种形式使用。

生成live dom时涉及另一个重要的知识点$compile,完整的实现方式我会在后面2.6节“指令”中讲解。

继续阅读