2.1:你的第一个AngularJS App
本章,带你体验一个简单的开发流程,将一个静态的使用模拟数据的应用,变成具有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的更多相关文章
- trackr: An AngularJS app with a Java 8 backend – Part II
该系列文章来自techdev The Frontend 在本系列的第一部分我们已经描述RESTful端建立在Java 8和Spring.这一部分将介绍我们的第一个用 AngularJS建造的客户端应用 ...
- angular.js的ng-app 指令定义一个 AngularJS 应用程序。
<!DOCTYPE html> <html lang="en" ng-app> <head> <meta charset="UT ...
- [已开源/文章教程]独立开发 一个社交 APP 的源码/架构分享 (已上架)
0x00 背景 真不是和被推荐了2天的博客园一位大神较真,从他那篇文章的索引式文章内容也学习到了很多东西,看评论区那么多对社交APP源码有兴趣的,正巧我上周把我的一个社交APP开源了,包括androi ...
- 记一个社交APP的开发过程——基础架构选型(转自一位大哥)
记一个社交APP的开发过程——基础架构选型 目录[-] 基本产品形态 技术选型 最近两周在忙于开发一个社交App,因为之前做过一点儿社交方面的东西,就被拉去做API后端了,一个人头一次完整的去搭这么一 ...
- 如何用 React Native 创建一个iOS APP?(三)
前两部分,<如何用 React Native 创建一个iOS APP?>,<如何用 React Native 创建一个iOS APP (二)?>中,我们分别讲了用 React ...
- 如何用 React Native 创建一个iOS APP?(二)
我们书接上文<如何用 React Native 创建一个iOS APP?>,继续来讲如何用 React Native 创建一个iOS APP.接下来,我们会涉及到很多控件. 1 AppRe ...
- 如何用 React Native 创建一个iOS APP?
诚然,React Native 结合了 Web 应用和 Native 应用的优势,可以使用 JavaScript 来开发 iOS 和 Android 原生应用.在 JavaScript 中用 Reac ...
- (Android+IOS)我们正在做一个新闻App,做几乎一样的,倾听您的建议 (画画)
(Android+IOS)我们正在做一个新闻App,做几乎一样的,倾听您的建议! 新闻采访是做,前端展示APP界面感觉还不是非常好,还须要改进改进,希望公布(Android和IOS版本号)前听听大家的 ...
- VS2015下的Android开发系列02——用VS开发第一个Android APP
配置Android模拟器 这算是第一篇漏下说的,配置好VS的各参数,新建Android项目后,会发现菜单下的工具栏会多出Android相关的工具栏,红色圈出的就是AVD. 打开AVD后可以从模版处选一 ...
随机推荐
- django忘记管理员账号和密码处理
1.忘记密码: >>> from django.contrib.auth.models import User >>> user = User.object.get ...
- Android PickerView滚动选择器的使用方法
手机里设置闹钟需要选择时间,那个选择时间的控件就是滚动选择器,前几天用手机刷了MIUI,发现自带的那个时间选择器效果挺好看的,于是就自己仿写了一个,权当练手.先来看效果: 效果还行吧?实现思路就是自定 ...
- 30天,O2O速成攻略【7.19深圳站】
活动概况 时间:2015年07月19日13:30-16:30 地点:深圳腾讯大厦(南山区科技园科技中一路)2楼多功能厅 主办:APICloud.OneAPM.连接科技 网址:www.apicloud. ...
- 通过sqlserver日志恢复误删除的数据
如果你已经急的焦头烂额,看到这篇文章的时候,请你换个坐姿,深呼吸几次,静下心来将这篇文章读完,也许你的问题迎刃而解. 我遇到的情况是这样的,网站被植入木马,盗取了我的web.config文件,web ...
- UIlabel多行文字自动换行 (自动折行)
UIView *footerView = [[UIView alloc]initWithFrame:CGRectMake(, , , )]; UILabel *label = [[UILabel al ...
- 5、JavaScript进阶篇②——函数、事件、内置对象
一.函数 1. 什么是函数 函数的作用,可以写一次代码,然后反复地重用这个代码. 如:我们要完成多组数和的功能. var sum; sum = 3+2; alert(sum); sum=7+8 ; a ...
- QString 和 TCHAR 的相互转换
参考资料: http://www.cnblogs.com/fuyanwen/p/3200536.htmlhttp://www.cnblogs.com/wendao/archive/2012/07/27 ...
- Hadoop学习(3)-- 安装1.x版本
Hadoop有三种安装模式,分别为单机模式.伪分布式模式和完全分布式模式(集群模式).本文安装版本是hadoop-1.1.2,hadoop-2.x版本安装请参考:http://www.cnblogs. ...
- 清除mstsc远程登录记录
这里提供一串清除mstsc远程登录记录的命令 @echo off set TMP1=%cd%echo %TMP1%reg delete "HKEY_CURRENT_USER\Software ...
- sql语句查询出数据重复,取唯一数据
select distinct mr.id,ifnull(mr.pid,0) as pid,mr.name from sys_role_res srr left join main_res mr on ...