本章,带你体验一个简单的开发流程,将一个静态的使用模拟数据的应用,变成具有AngularJS特性的动态web应用。在6-8章,作者将展示如何创建一个更复杂,更真实的AngularJS应用。

1、准备项目

在项目路径下,新建todo.html,代码如下:

<!DOCTYPE html>
<html data-ng-app>
<head>
<title>TO DO List</title>
<link href="bootstrap.css" rel="stylesheet" />
<link href="bootstrap-theme.css" rel="stylesheet" />
</head>
<body>
<div class="page-header">
<h1>Adam's To Do List</h1>
</div>
<div class="panel">
<div class="input-group">
<input class="form-control" />
<span class="input-group-btn">
<button class="btn btn-default">Add</button>
</span>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>Description</th>
<th>Done</th>
</tr>
</thead>
<tbody>
<tr><td>Buy Flowers</td><td>No</td></tr>
<tr><td>Get Shoes</td><td>No</td></tr>
<tr><td>Collect Tickets</td><td>Yes</td></tr>
<tr><td>Call Joe</td><td>No</td></tr>
</tbody>
</table>
</div>
</body>
</html>

该静态页面已经正常显示。到第六章时,作者会讲应用的文件结构。

2、使用AngularJS

用户能用该网页,查看要做的事项的列表,检查事项是否完成,创建一个新的事项。

2.1、应用AngularJS到HTML文件

<html ng-app="todoApp">
<head>
<title>TO DO List</title>
<link href="bootstrap.css" rel="stylesheet" />
<link href="bootstrap-theme.css" rel="stylesheet" />
<script src="angular.js"></script>
<script>
var todoApp = angular.module("todoApp", []);
</script>
</head>

AngularJS apps,从一个或多个模块开始。模块是通过调用angular.module方法创建的,如下面那样:

var todoApp = angular.module("todoApp", []);

作者将在第9和第18章描述模块的属性。angular.module方法的参数,是要创建的模块的名字,和模块需要的其他东西的数组。作者创建了一个叫做todoApp的模块。遵循约定,模块的名字以App结尾。因为不需要AngularJS提供其他模块,所以传递空数组作为第二个参数。作者将在第18章,展示不同模块可用的特性。

作者通过ng-app属性,告诉AngularJS如何应用模块。AngularJS通过给HTML添加新的元素、属性、类和special comments,来扩展HTML,才能工作。AngularJS库动态编译HTML,为了定位和处理这些附加信息,并创建一个应用。你可以通过JavaScript代码,客制化应用的行为,补充内建功能,定义你自己的附加信息到HTML上。

注意:AngularJS的编译器,不像你碰到的C#或Java项目的编译器那样,处理源代码,为了生成可以执行的运行时输出。精确地说,当浏览器已经加载内容,AngularJS库评估HTML元素,并使用标准DOM API和JavaScript特性,来添加或一处元素,设置事件处理器,等等。在AngularJS开发中,没有明确的变异步骤,只需要修改你的HTML和Javascript文件,并用浏览器加载他们。

AngularJS附加到HTML上,最重要的就是ng-app属性,它制定该html元素列表包含一个应该被AngularJS编译和处理的模块。当使用的JavaScript框架只有AngularJS时,习惯将ng-app属性应用到html元素。如果你要将AngularJS和其他技术混合,如jQuery,你可以通过在文档上的一个元素上应用ng-app属性,来收缩AngularJS app的边界。

2.2、给HTML应用AngularJS

给HTML文档添加一个非标准的属性,看起来很奇怪,特别是如果你已经写过一些web apps,并严格遵守HTML标准。有一个替代方式,使用data属性,给AngularJS添加data-前缀。

<html data-ng-app="todoApp">

作者会继续使用AngularJS约定,并使用ng-app属性,和其他HTML增强属性。他建议咱们也这样做。如果你的开发工具不能处理非标准的HTML元素和属性,你也可以不这么做。

3、创建一个数据模型

AngularJS支持MVC模式。作者将在第3章讲MVC。简单来讲,遵循MVC模式,需要你把应用分成三个确切的区域:应用中数据(model),对数据的操作逻辑(controllers),显示数据的逻辑(Views)。

<script>
var model = {
user: "Adam",
items: [{ action: "Buy Flowers", done: false },
{ action: "Get Shoes", done: false },
{ action: "Collect Tickets", done: true },
{ action: "Call Joe", done: false }]
};
var todoApp = angular.module("todoApp", []);
</script>

提示:作者说,model也可以包含create,load,store,modify数据对象所必须的逻辑。在一个AngularJS应用中,该逻辑一般放在服务器,被web server访问。作者将在第3章详细介绍。

提示:在任何AngularJS开发项目中,你不得不定义MVC主要部分的作用域。作者保证,在第6章可以看到一个大型的例子。它有很多初始化设置和必须的配置。

4、创建一个Controller

Controller定义了业务逻辑,为view提供支持。定义一个controller的最好方法,是解释什么种类的逻辑,是它不支持的,而什么是它支持的。

逻辑,是处理存储或获取模型的部分数据。逻辑,处理格式化过的数据,将它作为VIEW的一部分,显示给用户。Controller在model和view之间,并连接他们。Controller相应用户交互,更新model中的数据,提供view和view必须的数据。

作者说,不用担心,本书结束时,你将学会MVC模式,和在AngularJS中应用他们。

通过调用angular.module返回的模型对象的controller方法,创建一个controller。controller方法的参数,是新controller的名字,和他的功能。

todoApp.controller("ToDoCtrl", function ($scope) {
$scope.todo = model;
});
</script>
</head>
<body ng-controller="ToDoCtrl">

controller的命名约定,是以Ctrl结尾。

你不会总是想让views访问整个model,所以你希望使用controller,来明确地选择一部分数据,这叫做scope(范围)。

我的controller函数的参数,调用了$scope,这就是说,$符号跟随者单词scope。在AngularJS app中,以$开始的变量名,表示是AngularJS提供的内建特性。当你看到$符号,它一般指向一个内建的服务,它是一个自包含的组建,为多个控制器提供特性。但$scope很特别,它用于曝露数据和函数给view。作者将在第13章讲解scope,在18-25章讲解内建services。

对于本应用而言,作者系统它在view中使用整个model,所以他定义了一个属性,在$scope服务对象上,调用todo,并像下面那样,指派完整的model:

$scope.todo = model;

作者也不得不指定controller负责的html文档的区域。因为是一个简单的应用,并且只有一个controller,作者就在body元素上应用ng-controller。

<body ng-controller="ToDoCtrl">

ng-controller属性的值,是要设置的controller的名字。作者将在第13章深入controller的主题。

4、创建一个View

作者将在下面的代码中,演示如何使用一种注释类型,也叫做数据绑定。

<h1>
{{todo.user}}'s To Do List
<span class="label label-default">{{todo.items.length}}</span>
</h1> <tbody>
<tr ng-repeat="item in todo.items">
<td>{{item.action}}</td>
<td>{{item.done}}</td>
</tr>
</tbody>
5、插入Model View
AngularJS使用双花括号{{}},来代表一个数据绑定表达式。表达式的内容,
作为JavaScript,被求值,通过使用Controller,来限制数据和功能被分配给scope。
在本例中,作者只能访问它在定义controller时,使用在$scope对象创建的属性名,来访问指派给$scope对象的那部分数据。
这意味着,例如,如果作者想访问model.user属性,作者定义一个数据绑定表达式,
引用todo.user。这就是为什么,作者给$scope.todo属性指派model对象。
    AngularJS编译文档中的HTML,发现ng-controller属性,让ToDoCtrl函数设置用于创建view的范围。遇到的每个数据绑定表达式,AngularJS在$scope对象中查找指定的值,
并添加该值到HTML文档。例如,下面的例子:
{{todo.user}}'s To Do List

它会被处理,并翻译为下面的字符串:

Adam's To Do List

这就是所谓的数据绑定或模型绑定,model中的值,绑定到一个html元素的内容上。这里有一些不同的方式来创建数据绑定,作者将在第10章解释。

6、求表达式的值

一个数据绑定表达式的内容,可以是任何可用的JavaScript声明,意味着你能执行操作,从model中创建新的数据。下面是显示to-do items的个数:

<div class="page-header">
{{todo.user}}'s To Do List<span class="label label-default">{{todo.items.length}}</span>
</div>

提示:在表达式中,应该只执行简单的操作。不要使用数据绑定,来执行复杂逻辑或对model的操作。这应该是controller的工作。你会经常遇到很难讲逻辑归类于view或controller的情况。作者的建议是,不要担心它。以最快的速度开发,再以后需要时再移动这些逻辑。如果实在不知道该怎么做,就把逻辑放在controller中,它有60%的几率是正确的。

7、使用指令

表达式中也可以使用指令,这会告诉AngularJS,你想要怎么处理内容。在本课中,作者使用ng-repeat属性。

<tr ng-repeat="item in todo.items">
<td>{{item.action}}</td><td>{{item.done}}</td>
</tr>

它会产生下面的代码

<tr ng-repeat="item in todo.items" class="ng-scope">
<td class="ng-binding">Buy Flowers</td>
<td class="ng-binding">false</td>
</tr>
<tr ng-repeat="item in todo.items" class="ng-scope">
<td class="ng-binding">Get Shoes</td>
<td class="ng-binding">false</td>
</tr>
<tr ng-repeat="item in todo.items" class="ng-scope">
<td class="ng-binding">Collect Tickets</td>
<td class="ng-binding">true</td>
</tr>
<tr ng-repeat="item in todo.items" class="ng-scope">
<td class="ng-binding">Call Joe</td>
<td class="ng-binding">false</td>
</tr>

ng-repeat指令,会是你最常用的指令之一。

8、超越基本

8.1使用双向模型绑定

作者之前使用的绑定,都是单向绑定,从model中取出值,用于在模板中分发这些元素。这是一个相当基本的材料,并且在web app开发中,广泛使用的技术。例如,作者在使用jQeury时,经常使用Handlebars模板包,它提供该类型的绑定,对从数据对象生成HTML内容很有用。

AngularJS也提供双向绑定,用模型生成元素,当元素改变时,导致模型也相应的改变。

<tr ng-repeat="item in todo.items">
<td>{{item.action}}</td>
<td><input type="checkbox" ng-model="item.done" /></td>
<td>{{item.done}}</td>
</tr>

作者添加了一个checkbox input元素。重要的附加信息,是ng-model属性,它告诉AngularJS,在input元素的值和相应数据对象的done属性之间,创建一个双向绑定。

当HTML第一次编译,AngularJS会使用done属性的value,设置input元素的value。

AngularJS的绑定是动态的,双向的绑定。两个元素绑定到同一个,一个元素变了,另一个也会变。

双向绑定,可以应用于用户输入的元素,生成使用HTML表单元素关联的有意义的元素。作者会在第12章深度讲解。

8.2、创建并使用控制器行为

控制器在范围上定义行为。行为,是操作model上的数据,以实现应用中的业务逻辑的功能。行为,通过controller定义,支持一个view,以显示数据,并基于用户交互更新模型。

todoApp.controller("ToDoCtrl", function ($scope) {
$scope.todo = model;
$scope.incompleteCount = function () {
var count = 0;
angular.forEach($scope.todo.items, function (item) {
if (!item.done) { count++ }
});
return count;
}
}); <div class="page-header">
<h1>
{{todo.user}}'s To Do List
<span class="label label-default" ng-hide="incompleteCount() == 0">
{{incompleteCount()}}
</span>
</h1>
</div>

通过给传递给controller 函数的$scope对象添加功能,来定义行为。

提示:作者使用angular.forEach方法,来枚举数组的内容。AngularJS包含许多有用的工具方法,补充JavaScript语言。作者将在第4章描述这些工具方法。

附加在$scope对象上的属性名,作为行为的名字。作者的行为叫做incompleteCount,可以在ng-countroller属性的范围内,调用他。

ng-hide指令的表达式为true时,会隐藏元素。

提示:ng-hide是基于AngularJS model状态自动操作DOM的大量指令中的一个。作者会在第11章详细讲解,并在15-17章教咱们如何创建自己的指令。

8.3、使用其他行为

$scope.warningLevel = function () {
return $scope.incompleteCount() < 3 ? "label-success" : "label-warning";
}<div class="page-header">
<h1>
{{todo.user}}'s To Do List
<span class="label label-default" ng-class="warningLevel()"
ng-hide="incompleteCount() == 0">
{{incompleteCount()}}
</span>
</h1>
</div>

作者定义了一个叫做warningLevel的行为,它基于完成的to-do items的个数,返回Bootstrap CSS class的名字。

8.4相应用户交互

你已经看到如何将行为和指令结合在一起,创建app 特性,这种结合,将派生许多AngularJS app的功能。一个最强大的结合,是实现响应用户的交互。

$scope.addNewItem = function (actionText) {
$scope.todo.items.push({ action: actionText, done: false });
}

<div class="input-group">
<input class="form-control" ng-model="actionText" />
<span class="input-group-btn">
<button class="btn btn-default"
ng-click="addNewItem(actionText)">Add</button>
</span>
</div>

作者添加了一个叫做addNewItem的行为,它持有一个新to-do item的文本,并添加一个对象到数据模型,使用该文本作为action属性的值,并设置done属性为false。

这是作者展示的第一个修改model的行为。注意,该行为依然作为一个标准的Javascript函数被定义。

ng-click指令,这只一个处理器,当click事件被处罚,计算表达式的值。在本例中,表达式指向addNewItem行为,传递动态actionText属性作为参数。

8.5过滤和排序模型数据

在第14章,作者介绍了AngularJS过滤特性。

<tr ng-repeat="item in todo.items | filter:{done: false}
 | orderBy:'action'">
<td>{{item.action}}</td>
<td><input type="checkbox" ng-model="item.done" /></td>
</tr>

过滤可以应用到数据模型的任何部分。

提示:作者在orderBy里,使用字符串,作为属性值。使用’‘单引号。默认地,AngularJS假设scope定义的任何东西都是一个属性,并且不用引号,会查找一个叫做action的scope属性。这在你以编程的方式定义值时,会很有用。但是不意味着你不得不记住使用字符值,当你想要制定一个常熟。

model中的数据并没有被排序,排序操作时在ng-repeat指令用于执行创建table的row时,执行的。

8.6、改善过滤器

todoApp.filter("checkedItems", function () {
return function (items, showComplete) {
var resultArr = [];
angular.forEach(items, function (item) {
if (item.done == false || showComplete == true) {
resultArr.push(item);
}
});
return resultArr;
}
});

该过滤方法创建了一个过滤fatory,它返回一个功能,用于过滤一组数据对象。items参数,由AngularJS提供,是一组要被过滤的对象。当作者应用过滤器时,他会为showComplete参数提供一个值,它用于表明,是否显示已经完成的人物。

<tbody>
<tr ng-repeat=
"item in todo.items | checkedItems:showComplete | orderBy:'action'">
<td>{{item.action}}</td>
<td><input type="checkbox" ng-model="item.done" /></td>
</tr>
</tbody>
</table>
<div class="checkbox-inline">
<label><input type="checkbox" ng_model="showComplete">
 Show Complete</label>
</div>

这个自定义的过滤器,和内建的过滤器一样。我使用filter作为过滤器的方法名,使用一个:,后面跟随一个我想要传递给过滤器函数的模型属性名。

8.7通过Ajax获取数据

作者将在第五章讲解JSON。创建一个todo.json文件,内容如下:

[{ "action": "Buy Flowers", "done": false },
{ "action": "Get Shoes", "done": false },
{ "action": "Collect Tickets", "done": true },
{ "action": "Call Joe", "done": false }]
<PRE><SPAN style="COLOR: #000000">var model = {
user: "Adam"
};
var todoApp = angular.module("todoApp", []);
todoApp.run(function ($http) {
$http.get("todo.json").success(function (data) {
model.items = data;
});
});</SPAN></PRE>

调用AngularJS模块对象定义的run方法,该方法执行一个函数,它只有AngularJS已经执行初始化设置后执行一次,用于one-off任务。

我制定$http,作为传递给run方法的函数的参数,它告诉AngularJS,我想要使用为Ajax调用提供支持的服务对象。使用参数告诉AngularJS,你需要哪个特性,这叫做依赖注入。作者将在第9章介绍。

$http服务提供访问低级Ajax请求。低级在本例中,并不低。除非和$resources服务作比较。该服务用于和RESTful web services互动。作者将在第3章讲REST,在第12章讲$resource。作者使用$http.get方法,做了一个HTTP GET请求,从服务要todo.json文件。

get方法的结果,是一个许诺,他是一个对象。作者会在第5章讲解,在第20章深入讲解。在许诺对象上,调用success方法,当Ajax请求完成时,JSON数据从服务端返回,转换为一个Javascript对象,传递到作者的success函数作为data参数。作者使用收到的数据,更新模型。

2.1:你的第一个AngularJS App的更多相关文章

  1. trackr: An AngularJS app with a Java 8 backend – Part II

    该系列文章来自techdev The Frontend 在本系列的第一部分我们已经描述RESTful端建立在Java 8和Spring.这一部分将介绍我们的第一个用 AngularJS建造的客户端应用 ...

  2. angular.js的ng-app 指令定义一个 AngularJS 应用程序。

    <!DOCTYPE html> <html lang="en" ng-app> <head> <meta charset="UT ...

  3. [已开源/文章教程]独立开发 一个社交 APP 的源码/架构分享 (已上架)

    0x00 背景 真不是和被推荐了2天的博客园一位大神较真,从他那篇文章的索引式文章内容也学习到了很多东西,看评论区那么多对社交APP源码有兴趣的,正巧我上周把我的一个社交APP开源了,包括androi ...

  4. 记一个社交APP的开发过程——基础架构选型(转自一位大哥)

    记一个社交APP的开发过程——基础架构选型 目录[-] 基本产品形态 技术选型 最近两周在忙于开发一个社交App,因为之前做过一点儿社交方面的东西,就被拉去做API后端了,一个人头一次完整的去搭这么一 ...

  5. 如何用 React Native 创建一个iOS APP?(三)

    前两部分,<如何用 React Native 创建一个iOS APP?>,<如何用 React Native 创建一个iOS APP (二)?>中,我们分别讲了用 React ...

  6. 如何用 React Native 创建一个iOS APP?(二)

    我们书接上文<如何用 React Native 创建一个iOS APP?>,继续来讲如何用 React Native 创建一个iOS APP.接下来,我们会涉及到很多控件. 1 AppRe ...

  7. 如何用 React Native 创建一个iOS APP?

    诚然,React Native 结合了 Web 应用和 Native 应用的优势,可以使用 JavaScript 来开发 iOS 和 Android 原生应用.在 JavaScript 中用 Reac ...

  8. (Android+IOS)我们正在做一个新闻App,做几乎一样的,倾听您的建议 (画画)

    (Android+IOS)我们正在做一个新闻App,做几乎一样的,倾听您的建议! 新闻采访是做,前端展示APP界面感觉还不是非常好,还须要改进改进,希望公布(Android和IOS版本号)前听听大家的 ...

  9. VS2015下的Android开发系列02——用VS开发第一个Android APP

    配置Android模拟器 这算是第一篇漏下说的,配置好VS的各参数,新建Android项目后,会发现菜单下的工具栏会多出Android相关的工具栏,红色圈出的就是AVD. 打开AVD后可以从模版处选一 ...

随机推荐

  1. Linux就这个范儿 第9章 特种文件系统

    Linux就这个范儿 第9章 特种文件系统 http://book.douban.com/reading/32081222/ P326 有一种文件系统,根本不在磁盘上.这种文件系统就是大名顶顶的ram ...

  2. 话说 依赖注入(DI) or 控制反转(IoC)

    科普:首先依赖注入和控制反转说的是同一个东西,是一种设计模式,这种设计模式用来减少程序间的耦合,鄙人学习了一下,看TP官网还没有相关的文章,就写下这篇拙作介绍一下这种设计模式,希望能为TP社区贡献一些 ...

  3. SQLServer找出执行慢的SQL语句

      SELECT (total_elapsed_time / execution_count)/1000 N'平均时间ms' ,total_elapsed_time/1000 N'总花费时间ms' , ...

  4. RFS_javascript的使用

    1. RFS对javascript的调用 (1)调用javascript语句 (2)调用javascript函数 2. IE8不支持javascript的 getElementsByClassName ...

  5. json不支持中文写入的问题解决

    写两个函数,使其支持中文: function arrayRecursive(&$array, $function, $apply_to_keys_also = false) { foreach ...

  6. Hadoop学习笔记: 安装配置Hadoop

    安装前的一些环境配置: 1. 给用户添加sudo权限,输入su - 进入root账号,然后输入visudo,进入编辑模式,找到这一行:"root ALL=(ALL) ALL"在下面 ...

  7. VS2013+qt-vs-addin-1.2.4安装配置

    --------------------------开头这部分可以跳过,仅作为笔记----------------------- 我问过的问题: http://www.codeproject.com/ ...

  8. uiimageView连续帧动画

    // //  MJViewController.m //  05-汤姆猫 // //  Created by apple on 14-3-24. //  Copyright (c) 2014年 itc ...

  9. ios理解 -- Pro Mutlithreading and Memory Management for iOS and OS X with ARC, Grand Central Dispatch, and Blocks

    Capturing automatic variables Next, you need to learn what the “together with automatic (local) vari ...

  10. PG sys function

    The System Catalogs of PostgreSQLscott=# \dS List of relations Schema | Name | Type | Owner -------- ...