前面我们讲解了如何创建模块,但是拿他们来干什么呢?到目前为止它们只是空模块。<!-more->
核心原则
现在让我们讲解控制器。控制器在 AngularJS 中是干粗活的,使用 JavaScript 函数执行大部分用户界面之类的工作。在 AngularJS 应用程序中控制器的一些共同职责包括:
- 从服务器为当前的用户界面获取正确的数据
- 决定显示给用户哪部分数据
- 表示层逻辑:比如怎样显示元素、显示用户界面的哪些部分、怎样给它们设置样式等。
- 用户交互:比如当用户点击会如何响应、应该怎样验证输入文本。
AngularJS 控制器几乎总是直接连接一个视图或 HTML。从来没有哪个控制器中不用于用户界面(这种业务逻辑适用于服务),它建立起模型(驱动应用程序的的数据)与视图(用户看到的交互的)之间的通道。
让我们来看一看如何为 notesApp
模块创建一个控制器:
<!DOCTYPE html>
<html ng-app="notesApp">
<head>
<title>Hello AngularJS</title>
</head>
<body ng-controller="MainCtrl">
Hello {{1 + 1}}nd time AngularJS
<script src="https://cdn.jsdelivr.net/angularjs/1.2.28/angular.min.js"></script>
<script type="text/javascript">
angular.module('notesApp', [])
.controller('MainCtrl', [function() {
// Controller specific code goes here
console.log('MainCtrl has been created');
}]);
</script>
</body>
</html>
我们使用 AngularJS 模块暴露的 controller 方法定义了一个控制器。controller 方法的第一个参数表示控制器名称,上面例子中创造性地将其命名为 MainCtrl
。 第二个参数是控制器的实际定义,表示它做什么以及如何做。
此处有一个令人稍微费解的地方,即数组表示法。注意,我们在数组内部定义了控制器函数。也就是说,模块上的控制器函数的第一个参数表示控制器名称 MainCtrl
,第二个参数是一个数组。数组由控制器的所有依赖项的字符串变量构成,数组中的最后一个参数是实际的控制器函数。在这种情况下,因为没有依赖关系,函数是数组中唯一的参数,该参数包含所有控制器代码。
我们还引入一个新指令,ng-controller。它告诉 AngularJS 用给定名称去实例化控制器实例,并将其附加到 DOM 元素上。在这种情况下,AngularJS 会加载 MainCtrl
,最终将打印 console.log()
语句。
现在,我们将为第一个 AngularJS 应用使用控制器,将 hello world 消息从 HTML 移到控制器,从控制器获取并显示它。
让我们来看一看下面代码:
<!DOCTYPE html>
<html ng-app="notesApp">
<head>
<title>Notes App</title>
</head>
<body ng-controller="MainCtrl as ctrl">
{{ctrl.message}} AngularJS.
<button ng-click="ctrl.changeMessage()">
Change Message
</button>
<script src="https://cdn.jsdelivr.net/angularjs/1.2.28/angular.min.js"></script>
<script type="text/javascript">
angular.module('notesApp', [])
.controller('MainCtrl', [function () {
var self = this;
self.message = 'Hello ';
self.changeMessage = function () {
self.message = 'Goodbye ';
};
}]);
</script>
</body>
</html>
点击此处查看效果。
用户界面应该如下图所示。
是的,我们只看到 Hello AngularJS。 用户界面中没有显示 Goodbye。让我们深入研究这个例子,看看我们能否清楚正在发生什么事情:
- 正如我们之前看到的我们定义了
notesApp
模块。 - 我们使用模块的 controller 方法创建了名为
MainCtrl
的控制器。 - 我们定义了控制器实例的
helloMsg
(使用 this 关键字)变量,变量goodbyeMsg
作为控制器实例的局部变量(使用var
关键字)。 - 我们通过使用另一个指令:ngcontroller 在用户界面中使用该控制器。这个指令允许我们将控制器实例与用户界面元素关联(在本例中的 body 标记)。
- 当使用 ngcontroller 时我们也给
MainCtrl
实例一个特殊名称,这里我们称之为 ctrl。这在 AngularJS 中被称为 controllerAs 语法,在 HTML 中我们可以给每个控制器实例一个名称以识别它们的作用。 - 然后我们使用双大括号标记将
helloMsg
和goodbyeMsg
变量从控制器关联到 HTML。
很明显使用 this 关键字的定义控制器变量可以从 HTML 访问,局部变量则不行。
此外,任何控制器实例定义的变量(控制器中使用 this
, 而不是 var
关键字声明变量如 goodbyeMsg
)可以访问并通过 HTML 显示给用户。基本上就是我们如何从控制器给用户界面注入公开数据和业务逻辑。
用户需要看到 HTML 需要使用的任何东西,需要使用 this
来定义。HTML 不需要直接访问的任何东西不应该放在这里,应该在控制器范围中将它们保存为本地变量,类似于 goodbyeMsg
。
在我们深入研究 AngularJS 是如何工作之前让我们多看一个例子:
<!DOCTYPE html>
<html ng-app="notesApp">
<head>
<title>Notes App</title>
</head>
<body ng-controller="MainCtrl as ctrl">
{{ctrl.message}} AngularJS.
<button ng-click="ctrl.changeMessage()">
Change Message
</button>
<script src="https://cdn.jsdelivr.net/angularjs/1.2.28/angular.min.js"></script>
<script type="text/javascript">
angular.module('notesApp', [])
.controller('MainCtrl', [function () {
var self = this;
self.message = 'Hello ';
self.changeMessage = function () {
self.message = 'Goodbye ';
};
}]);
</script>
</body>
</html>
与前面的实例相比有什么不同呢?
- 现在只对
ctrl.message
变量绑定。 - 有个标签为 Change Message 的按钮。有一个内置的指令 ng-click,我们将一个函数作为其参数。当单击按钮时,ng-click 指令评估传递给的它任何表达式。在这种情况下,我们知道 AngularJS 触发了控制器的
changeMessage()
函数。 - 控制器的
changeMessage()
函数将信息参数值设置成Goodbye
。 - 另外,作为良好的实践,我们应避免在指控制器内的
this
关键字,使用self
代理变量引用this
。后面将解释为什么这是推荐的。
深入理解
我们以 Hello AngularJS 应用开始演示。但我们单击按钮时,文本变为 Goodbye AngularJS。。这是 AngularJS 数据绑定的威力。上面实例有几值得注意地方:
- 我们写的控制器没有直接访问视图或任何需要更新 DOM 元素,它是纯 JavaScript。
- 当用户点击按钮触发 changeMessage 函数,没有必要通知更新用户界面,它会自动更新。
- HTML 将部分 DOM 连接到控制器、函数和变量,而没有其它方式。
这是 AngularJS 的一个核心原则在起作用。基于数据驱动, 模型即真理 ,这意味着 AngularJS 应用核心应该是操作和修改模型(纯 JavaScript),其它重活就让 AngularJS 来做吧。
评论 (0)