是时候用AngularJS生成我们的动态页面了。
通常我们有很多方法来构建一个应用的代码。对于Angular的应用,我们鼓励使用来解耦代码并且实现职责独立。记住这个,现在让我们在我们的应用中使用一点Angular和Javascript来添加模型,视图和控制器成分。
·列表中的三部电话是由数据动态生成的。
最重要的不同将会在下面阐述,您可以点击在GitHub上查看所有的不同。
视图和模板
在Angular中,视图是数据模型通过html模板的映射。这意味着无论何时模型改变了,Angular将会刷新适当的数据绑定域,也就是更新视图。
在这个模板中,视图是被Angular生成的:
app/index.html
:
...
- { {phone.name}}
{
{phone.snippet}}
我们通过ngRepeat指令和两条Angular表达式替换了硬编码的电话列表:
·在<li>标签中的ng-repeat="phone in phones"属性是Angular的迭代器。这个迭代器告诉Angular,使用<li>标签作为模板为列表中的每一部电话创建一个<li>标签。
·被双花括号绑定的({ { phone.name}}
和 { { phone.snippet}}
)将会被表达式的值替代。
我们添加了一条新的指令,叫做ngController,它在<body>标签上绑定了一个PhoneListController控制器。这时:
·在花括号中的表达式 ({ { phone.name}}
和{ { phone.snippet}}
) 意味着绑定,这涉及到我们的数据模型,而这又是在我们的PhoneListController控制器中建立的。
注意:我们通过使用ng-app="phonecatApp"
指定了一个Angular模块,这里phonecatApp是我们的模块名。这个模块包含PhoneListController控制器。
模型和控制器
数据模型(一个在文本中创建的简单的电话数组)现在被PhoneListController控制器实例化了。控制器仅仅是一个使用了$scope的构造函数:
app/app.js
:
// Define the `phonecatApp` modulevar phonecatApp = angular.module('phonecatApp', []);// Define the `PhoneListController` controller on the `phonecatApp` modulephonecatApp.controller('PhoneListController', function PhoneListController($scope) { $scope.phones = [ { name: 'Nexus S', snippet: 'Fast just got faster with Nexus S.' }, { name: 'Motorola XOOM™ with Wi-Fi', snippet: 'The Next, Next Generation tablet.' }, { name: 'MOTOROLA XOOM™', snippet: 'The Next, Next Generation tablet.' } ];});
这里我们声明了一个叫做PhoneListController的控制器并将其在AngularJS模块(phonecatApp)中注册,注意到在引导Angular应用的过程中,我们的ng-app(在<html>标签中)指令指定了phonecatApp模块作为加载模块。
虽然至今控制器并没有做很多事,但它扮演了一个非常重要的角色。通过提供我们数据模型的环境,控制器允许我们在模型和视图中建立数据绑定。我们在展示层,数据层和逻辑层建立了如下的联系:
·位于<body>标签中的ngController指令,引用了我们控制器的PhoneListController(位于javascript文件夹下的app.js).
·PhoneListController将电话数据传入了被注入到我们控制器函数的$scope,scope是root scope的一个典型后代(一旦应用被定义)。这个控制器scope是所有位于<body ng-controller="PhoneListController">标签中的绑定可以获取的。
作用域
在Angular中,作用域的概念是极其重要的。scope可以看做是粘合模板,数据模型和控制器一起工作的胶水。Anglular使用scopes,包含在模板,数据模型和控制器中的信息来保持数据模型和视图的独立但同步,任何数据模型的改变会反应到视图上;任何视图的改变也会反映的数据模型上。
(进一步学习scope,请参考。)
Angular中的作用域原型继承与其父作用域,沿着这种关系直到根作用域。直接在作用域中赋值使得在页面的不同部分分享数据和创建相互影响的应用变得非常容易。当这种做法被应用到原型和规模更小的应用时,这会很快在数据模型中导致紧耦合,同时也很难溯源修改。
在接下来的步骤中,我们将会学习到如何更好地组织我们的代码,通过将相关的应用和展示逻辑“打包”成独立的,可复用的实体,我们称之为“组件”(component)。
测试
用“Angular方式”来将控制器从视图中独立出来,可以容易地测试代码像它被生成那样。如果我们的控制器在全局命名空间中是可获取的,那我们可以通过一个模仿的作用域对象来实例化它:
describe('PhoneListController', function() { it('should create a `phones` model with 3 phones', function() { var scope = {}; var ctrl = new PhoneListController(scope); expect(scope.phones.length).toBe(3); });});
实验
在index.html中添加另一个绑定,比如:
Total number of phones: {
{phones.length}}
在控制器创建一条新的模型属性并将其绑定到模板上,比如:
$scope.name = "World";
并在index.html上添加绑定:
Hello, {
{name}}!
刷新你的浏览器来证实确实输出了“Hello,World”。
在index.html中使用迭代器来创建一张简单的表:
row number |
---|
{ {i}} |
现在,使将列表变为基于1的递增绑定:
row number |
---|
{ {i+1}} |
额外作业:尝试使用额外的ng-repeat来创建一张8x8的表。
总结
现在您已经创建了一个将视图,模型和控制器独立的动态应用,让我们接下来学习如何通过组件来改善我们应用的架构吧。