AngularJS概念概述和第一个使用例子
点击查看AngularJS系列目录
转载请注明出处:http://www.cnblogs.com/leosx/
概念概述
本节使用一个简单的例子简要介绍了AngularJS的重要组成部分。
| 概念 | 描述 |
| 模板(Template) | HTML的附加标记 |
| 指令(Directives) | 通过元素或者客户属性去扩展HTML |
| 模型(Model) | 用户和界面交互的数据的模型。 |
| 上下文(Scope) | 语境上下文,这样控制器,指令和表达式可以访问它里面的数据。 |
| 表达式(Expressions) | 可以从Scope(上下文)中访问变量和函数。 |
| 编译器(Compiler) | 解析模板和实例化指令和表达式 |
| 过滤器(Filter) | 格式表达式的值以显示给用户 |
| 视图(View) | 用户所看到的(DOM) |
| 数据绑定(Data Binding) | 模型和视图间同步数据的动作 |
| 控制器(Controller) | 试图(view)背后的业务逻辑 |
| 依赖注入(Dependency Injection) | 创建对象和函数的工厂 |
| 注入器(Injector) | 依赖注入的容器 |
| 模块(Module) | 对应用程序的不同部分,包括控制器,服务器,过滤器,指令进行配置注射器的容器 |
| 服务(Service) | 对于试图可重用的业务逻辑独立的功能部分 |
第一个例子:数据绑定
在下面的例子中,我们将建立一个表格来计算总价格。
<div ng-app ng-init="qty=1;cost=2">
<b>Invoice:</b>
<div>
Quantity: <input type="number" min="0" ng-model="qty">
</div>
<div>
Costs: <input type="number" min="0" ng-model="cost">
</div>
<div>
<b>Total:</b> {{qty * cost | currency}}
</div>
</div>
结果如下图:

这看起来像普通的HTML和一些新的标记的组合。在AngularJS中,这样的文件称为模板。当AngularJS启动应用程序时,它会使用编译器去分析和处理来自新的标记标识的模板。然后在加载,改造,呈现一个新的DOM到用户视图。
第一个新的标记是指令(directives)。它是HTML元素或者属性的一个特殊的行为。在上面的例子当中,我们使用了 ng-app 属性,这是一个指令,用于自动初始化我们的应用程序。AngularJS还为input元素定义了一些额外的指令,用于增加一些行为来扩展元素。例如:ng-model 指令,用来存储或者更新输入字段的值。
自定义指令访问DOM:在一个AngularJS应用程序中,唯一的一个允许去访问DOM的地方就是指令的范围内(Scope)。这点很重要,因为访问DOM元素是一件很难预测,也很难测试的事情。如果您需要直接访问DOM,你应该写一个自定义的指令去做这件事。
在指令章节,我们会去介绍如何自定义。
第二种新的标记是双花括号 {{表达|过滤器}} ,当编译器遇到这个标记,将其与标记的评估值替换。在模板中的表达式是一个类似于JavaScript的代码段,允许读取和写入变量。请注意,这些变量不是全局变量。就像AngularJS函数和这些变量在一个function函数里面一样,Angular可以去访问。在上面的例子当中,我们的花括号表达式的功能是计算数量和单价,以获得总价格。后面的过滤器使得我们的输出格式为金钱格式(这里加了一个$符号表示是美元为单位的)。在这个例子中,我们可以看到,AngularJS提供了一个绑定:当输入值发生变化,表达式的值会自动重新计算并且去更新DOM与之对应的值。这使用到的概念是双向数据绑定(学过WPF或者Silverlight的同学一定很清楚明白的)。
添加UI逻辑:控制器(controller)
让我们添加更多的逻辑,使我们能够进行不同货币的总价格计算。
第一个文件:invoice1.js
angular.module('invoice1', [])
.controller('InvoiceController', function() {
this.qty = 1;
this.cost = 2;
this.inCurr = 'EUR';
this.currencies = ['USD', 'EUR', 'CNY'];
this.usdToForeignRates = {
USD: 1,
EUR: 0.74,
CNY: 6.09
};
this.total = function total(outCurr) {
return this.convertCurrency(this.qty * this.cost, this.inCurr, outCurr);
};
this.convertCurrency = function convertCurrency(amount, inCurr, outCurr) {
return amount * this.usdToForeignRates[outCurr] / this.usdToForeignRates[inCurr];
};
this.pay = function pay() {
window.alert("Thanks!");
};
});
第二个文件:index.html
<div ng-app="invoice1" ng-controller="InvoiceController as invoice">
<b>Invoice:</b>
<div>
Quantity: <input type="number" min="0" ng-model="invoice.qty" required >
</div>
<div>
Costs: <input type="number" min="0" ng-model="invoice.cost" required >
<select ng-model="invoice.inCurr">
<option ng-repeat="c in invoice.currencies">{{c}}</option>
</select>
</div>
<div>
<b>Total:</b>
<span ng-repeat="c in invoice.currencies">
{{invoice.total(c) | currency:c}}
</span>
<button class="btn" ng-click="invoice.pay()">Pay</button>
</div>
</div>
效果图如下:

和上一个例子相比,有什么改变呢?
首先,增加了一个包含控制器的新的JavaScript文件。更确切地说,该文件包含一个构造函数用于去创建一个真实的Controller控制器的实例。控制器的目的就是为我们的表达式和指令去提供一些变量和方法。
除了增加了新的文件之外,我们还在HTML代码中增加了一个ng-controller指令,这个指令就是在告诉AngularJS,去创建一个InvoiceController去负责这个元素,以及这个元素下的所有子元素。语法:ng-controller="InvoiceController as invoice" 是告诉AngularJS去创建一个控制器,并重命名此控制器为invoce,这样下面访问控制器中的变量的时候,就可以使用invoce这个昵称去访问控制器所在的Scope中的变量了,HTML 中,还使用了ng-repeat指令去循环指定的元素。也定义了一个方法total (function)方法去计算总价格。
同样,这种结合是很灵活的,即当数据变化时,DOM会自动更新显示变化后的结果。这就省却了我们去修改DOM元素。我们使用了ng-click指令去绑定到了按钮点击事件上。这样,当点击按钮的时候,就会触发与controller的scope所对应的方法进行执行。
在新的JavaScript文件,我们还在Module中注册了我们的控制器模块。我们将在下一节讨论模块(module),下图显示了所有的东西是如何在Controller里面对应显示出来的。

独立的业务逻辑:服务
眼下,InvoiceController包含我们的例子中的所有逻辑。当我们的逻辑变得复杂之后,我们应该把一些可以独立出来的业务逻辑提出来,放到服务里面去,这样这些独立的业务逻辑块儿就可以重复使用了。之后,我们就可以从网络上加载一些独立的业务逻辑,如装载并调用雅虎的财经API来实现汇率的转换,而我们的控制器不用变。
服务文件:finance2.js
angular.module('finance2', [])
.factory('currencyConverter', function() {
var currencies = ['USD', 'EUR', 'CNY'];
var usdToForeignRates = {
USD: 1,
EUR: 0.74,
CNY: 6.09
};
var convert = function (amount, inCurr, outCurr) {
return amount * usdToForeignRates[outCurr] / usdToForeignRates[inCurr];
};
return {
currencies: currencies,
convert: convert
};
});
控制器文件:invoice2.js
angular.module('invoice2', ['finance2'])
.controller('InvoiceController', ['currencyConverter', function(currencyConverter) {
this.qty = 1;
this.cost = 2;
this.inCurr = 'EUR';
this.currencies = currencyConverter.currencies;
this.total = function total(outCurr) {
return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);
};
this.pay = function pay() {
window.alert("Thanks!");
};
}]);
HTML文件:index.html
<div ng-app="invoice2" ng-controller="InvoiceController as invoice">
<b>Invoice:</b>
<div>
Quantity: <input type="number" min="0" ng-model="invoice.qty" required >
</div>
<div>
Costs: <input type="number" min="0" ng-model="invoice.cost" required >
<select ng-model="invoice.inCurr">
<option ng-repeat="c in invoice.currencies">{{c}}</option>
</select>
</div>
<div>
<b>Total:</b>
<span ng-repeat="c in invoice.currencies">
{{invoice.total(c) | currency:c}}
</span>
<button class="btn" ng-click="invoice.pay()">Pay</button>
</div>
</div>
效果图:

这次又有什么变化呢?
我们新建了一个文件:finance2.js 并且把 convertCurrency功能移动到了文件当中去。但是我们又如何使得控制器依旧保持着这个功能呢?
这就是依赖注入的用武之地。依赖注入(DI)是软件设计的一部分,它实现了如何创建对象(object)和功能函数(function),以及如何正确找到它们的依赖关系。在Angular中,所有的东西(指令,过滤器,控制器,服务,...)的创建都有使用依赖注入。在Angular中,DI的容器是注入器(injector)
要使用DI,我们首先是要在需要使用的地方进行注册。在Angular中,我们是在模块(modules)中进行注册的。当Angular启动时,它会执行模块的配置(config)然后根据ng-app指令开始执行,在执行前,模块会根据配置的名称去加载所有依赖的模块。
在上面的例子当中,包含了一个指令ng-app="invoice2"。这是在告诉Angular,应用程序的主模块适用名为:invoice2的模块作为主模块。代码段:angular.module('invoice2', ['finance2'])指定了invoice2的模块依赖于finance2模块。也就是说,InvoiceController 控制器使用了currencyConverter 服务中的功能。执行到这里Angular知道该应用程序的所有部分了,接下来就是去创建它们了。在上一节我们的控制器使用工厂函数来创建的。在服务方面有多种方式来定义自己的工厂(见服务指南)。在上面的例子中,我们在服务的工厂(factory)中使用了一个函数去返回了一个currencyConverter 函数功能。

回到最初的问题:如何在InvoiceController控制器中得到一个服务中的currencyConverter功能?在Angular中,这是通过在构造函数中简单地定义参数进行实现的。有了这个,injector能够根据顺序去创建正确的对象,并且在创建前,会先调用创建依赖对象并调用它们的工厂函数。在InvoiceController 中,有一个currencyConverter的参数,有了它,Angular就知道控制器和服务之间的依赖性,并调用与服务实例作为控制器的参数。
无论是上一个例子还是这一个例子,我们都可以看到,我们在module.controller 函数中,有一个数组,数组首先包含了控制器需要服务相关的名称,它就是在注册所依赖的模块。数组中的最后一项是控制器构造函数。Angular使用此数组语法定义的依赖关系,使得减少了代码污染DI。
访问后台服务
让我们来实现一下我们上面说到的,使用雅虎汇率服务API,去通过网络获得实时的汇率信息。
第一个文件:invoice3.js
angular.module('invoice3', ['finance3'])
.controller('InvoiceController', ['currencyConverter', function(currencyConverter) {
this.qty = 1;
this.cost = 2;
this.inCurr = 'EUR';
this.currencies = currencyConverter.currencies;
this.total = function total(outCurr) {
return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);
};
this.pay = function pay() {
window.alert("Thanks!");
};
}]);
第二个文件:finance3.js
angular.module('finance3', [])
.factory('currencyConverter', ['$http', function($http) {
var YAHOO_FINANCE_URL_PATTERN =
'//query.yahooapis.com/v1/public/yql?q=select * from '+
'yahoo.finance.xchange where pair in ("PAIRS")&format=json&'+
'env=store://datatables.org/alltableswithkeys&callback=JSON_CALLBACK';
var currencies = ['USD', 'EUR', 'CNY'];
var usdToForeignRates = {};
var convert = function (amount, inCurr, outCurr) {
return amount * usdToForeignRates[outCurr] / usdToForeignRates[inCurr];
};
var refresh = function() {
var url = YAHOO_FINANCE_URL_PATTERN.
replace('PAIRS', 'USD' + currencies.join('","USD'));
return $http.jsonp(url).success(function(data) {
var newUsdToForeignRates = {};
angular.forEach(data.query.results.rate, function(rate) {
var currency = rate.id.substring(3,6);
newUsdToForeignRates[currency] = window.parseFloat(rate.Rate);
});
usdToForeignRates = newUsdToForeignRates;
});
};
refresh();
return {
currencies: currencies,
convert: convert,
refresh: refresh
};
}]);
第三个文件:index.html
<div ng-app="invoice3" ng-controller="InvoiceController as invoice">
<b>Invoice:</b>
<div>
Quantity: <input type="number" min="0" ng-model="invoice.qty" required >
</div>
<div>
Costs: <input type="number" min="0" ng-model="invoice.cost" required >
<select ng-model="invoice.inCurr">
<option ng-repeat="c in invoice.currencies">{{c}}</option>
</select>
</div>
<div>
<b>Total:</b>
<span ng-repeat="c in invoice.currencies">
{{invoice.total(c) | currency:c}}
</span>
<button class="btn" ng-click="invoice.pay()">Pay</button>
</div>
</div>
效果图:

这个示例又有什么变化呢?我们的finance 模块的currencyConverter 服务,使用了$http,$http是一个AngularJS内置的用于访问服务器的后端数据的服务。$http 使用的是XMLHttpRequest 技术和 JSONP 进行传输.
AngularJS概念概述和第一个使用例子的更多相关文章
- 不用搭环境的10分钟AngularJS指令简易入门01(含例子)
不用搭环境的10分钟AngularJS指令简易入门01(含例子) `#不用搭环境系列AngularJS教程01,前端新手也可以轻松入坑~阅读本文大概需要10分钟~` AngularJS的指令是一大特色 ...
- 按照鬼哥学so变化,四,第一章的例子
跟随鬼哥伦比亚科学so变化,四.第一章的例子 图纸/文化 听鬼哥说故事 ---------------------------------------------切割线--------------- ...
- 从源码编译安装PCL并运行第一个小例子
如何通过源码编译方式安装PCL 对于很多想学习PCL的同学而言,往往会被如何安装困扰很长时间.我就是这其中的一员,为了不让大家在安装问题上浪费太多时间,我决心写下这篇小小的随笔,希望对大家有所帮助. ...
- Angular开发者指南(二)概念概述
template(模板):带有附加标记的模板HTML directives(指令):使用自定义属性和元素扩展HTML model(模型):用户在视图中显示的数据,并与用户进行交互 scope(作用域) ...
- 针对angularjs下拉菜单第一个为空白问题处理
angularjs 的select的option是通过循环造成的,循环的方式可能有 ng-option 或 者 <option ng-repeat></option ...
- 《hadoop权威指南》关于hive的第一个小例子的演示
本文是<hadoop权威指南>关于hive的小例子,通过这个例子可以很好地看出来hive是个什么东西. 前提是已经配置好hive的远程连接版本的环境,我是用了MYSQL数据库保存元数据. ...
- springmvc入门的第一个小例子
今天我们探讨一下springmvc,由于是初学,所以简单的了解一下 springmvc的流程,后续会持续更新... 由一个小例子来简单的了解一下 springmvc springmvc是spring框 ...
- NodeJS系列~第一个小例子,实现了request.querystring功能
返回目录 百度百科上: Node.js是一套用来编写高性能网络服务器的JavaScript工具包,一系列的变化由此开始,在Node中,Http是首要的.Node为创建http服务器作了优化,所以在网上 ...
- Camel In Action 阅读笔记 第一部分概述 + 第一章概述 认识Camel
第一部分: 最开始的一小步 Apache Camel 是一个开源集成框架,其目的是让系统集成变得更加简便,在本书的第一章中,我们会为您介绍它并向您展示它是如何在大型企业应用中做好集成工作.您也会了解到 ...
随机推荐
- TensorFlow框架(3)之MNIST机器学习入门
1. MNIST数据集 1.1 概述 Tensorflow框架载tensorflow.contrib.learn.python.learn.datasets包中提供多个机器学习的数据集.本节介绍的是M ...
- sed武功心法(info sed翻译+注解)
本文中的提到GNU扩展时,表示该功能是GNU为sed提供的(即GNU版本的sed才有该功能),一般此时都会说明:如果要写具有可移植性的脚本,应尽量避免在脚本中使用该选项. 本文中的正则表达式几乎和gr ...
- 容器在 Weave 中如何通信和隔离?- 每天5分钟玩转 Docker 容器技术(65)
上一节我们分析了 Weave 的网络结构,今天讨论 Weave 的连通和隔离特性. 首先在host2 执行如下命令: weave launch 192.168.56.104 这里必须指定 host1 ...
- LVS-DR实现web调度模式
author:JevonWei 版权声明:原创作品 实现LVS-DR调度web模式 拓扑环境 网络环境 RS1 RIP 192.168.198.138/24 VIP 192.168.198.100/3 ...
- [C]成员运算符"."和间接成员运算符"->"浅析
成员运算符: . 成员运算符一般和结构或者联合名一起使用,指定结构或者联合中的某个成员. 举个栗子: 如果Ronz是一个结构的名称,linux是这个结构模板指定的一个成员名. struct{ //匿名 ...
- 低版本浏览器支持HTML5标签的方法
最近刷了一道面试题,是关于低版本浏览器支持HTM5标签的写法,在网上找了一些,都行之有效,但是缺少整体总结,所以在这里总结一下,方便其他人过来阅读. IE低版本需要支持HTML5标签: 方法1.传统引 ...
- 微信iOS收款到账语音提醒开发总结
本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/yYCaPMxHGT9LyRyAPewVWQ 作者:l ...
- html5shiv.js和respond.min.js
做页面常用的东西,写这里用的时候省点去找了... html5shiv:解决ie9以下浏览器对html5新增标签的不识别,并导致CSS不起作用的问题. respond.min:让不支持css3 Medi ...
- js读取cookie、设置cookie
//-----------------------------直接调用函数就可以了------------------------------ setCookie("test",& ...
- poj 3592 缩点+SPFA
题意:给出一个矩阵,其中#代表墙,不可走,0-9代表权值,*代表可以选择传送.求从0,0点开始出发能获得最大权值. 思路:因为*的出现会有环的情况,先建图连边,将环进行Tarjan缩点,之后再从0,0 ...