Angular开发者指南(二)概念概述
template(模板):带有附加标记的模板HTML
directives(指令):使用自定义属性和元素扩展HTML
model(模型):用户在视图中显示的数据,并与用户进行交互
scope(作用域):存储模型的上下文,以便控制器,指令和表达式可以访问它
expressions(表达式):访问范围中的变量和函数
compiler(编译器):解析模板并实例化指令和表达式
filter(过滤器):格式化表达式的值以显示给用户
view(视图):用户看到的内容(DOM)
Data Binding(数据绑定):在模型和视图之间同步数据
controller(控制器):视图后面的业务逻辑
Dependency Injection:创建并连接对象和函数
injector(注入器):依賴注入容器
module(模块):一个用于应用程序不同部分的容器,包括控制器,服务,过滤器,配置Injector的指令
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然后称为视图。
第一种新的标记是指令。 它们对HTML中的属性或元素应用特殊的行为。 在上面的例子中,我们使用ng-app属性,它链接到一个自动初始化我们的应用程序的指令。 AngularJS还定义了一个为元素添加额外行为的输入元素的指令。 ng-model指令存储/更新输入字段的值到/自变量。
访问DOM的自定义指令:在AngularJS中,应用程序应该访问DOM的唯一位置是指令内。 这很重要,因为访问DOM的工件难以测试。 如果你需要直接访问DOM,你应该为它写一个自定义指令。
第二种新的标记是双花括号{{expression | filter}}:当编译器遇到这个标记时,它将用标记的估计值替换它。 模板中的表达式是一个类似JavaScript的代码片段,它允许AngularJS读取和写入变量。 请注意,这些变量不是全局变量。 就像JavaScript函数中的变量存在于作用域中一样,AngularJS为表达式可访问的变量提供了一个作用域。 存储在作用域上的变量中的值在文档的其余部分中称为模型。 应用于上面的示例,标记指示AngularJS“获取从输入小部件获取的数据并将它们相乘”。
上面的示例还包含一个过滤器。 过滤器格式化表达式的值以显示给用户。 在上面的示例中,过滤器货币将数字格式化为看起来像金钱的输出。
在示例中重要的是,AngularJS提供活动绑定:每当输入值更改时,表达式的值都会自动重新计算,并使用其值更新DOM。 这背后的概念是双向数据绑定。
添加UI逻辑:控制器
invoice1.js
angular.module('invoice1', [])
.controller('InvoiceController', function InvoiceController() {
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><br>
<button class="btn" ng-click="invoice.pay()">Pay</button>
</div>
</div>
首先,有一个包含控制器的新JavaScript文件。更准确地说,该文件指定将用于创建实际控制器实例的构造函数。控制器的目的是将变量和功能暴露给表达式和指令。
除了包含控制器代码的新文件,我们还向HTML添加了ng-controller指令。这个指令告诉AngularJS,新的InvoiceController负责具有指令的元素和所有元素的子元素。语法InvoiceController作为凭证告诉AngularJS实例化控制器并将其保存在当前作用域中的变量invoice 中。
我们还更改了页面中的所有表达式,以便在控制器实例中读取和写入变量,方法是在它们前面加上invoice 。 。可能的货币在控制器中定义,并使用ng-repeat添加到模板。由于控制器包含一个总函数,我们还可以使用{{invoice.total(...)}}将该函数的结果绑定到DOM。
再次,这种绑定是活的,即,当函数的结果改变时,DOM将被自动更新。用于支付发票的按钮使用指令ngClick。这将在每次点击按钮时评估相应的表达式。
在新的JavaScript文件中,我们还创建了一个模块,我们在其中注册控制器。我们将在下一节中讨论模块。
下图显示了在我们介绍控制器之后,一切是如何协同工作的:
独立于视图的业务逻辑:服务service
现在,InvoiceController包含我们示例的所有逻辑。 当应用程序增长时,将与视图无关的逻辑从控制器移动到服务中是一个好的做法,因此它也可以由应用程序的其他部分重用。 稍后,我们还可以更改该服务以从网络(例如网络)载入汇率。 通过调用Yahoo Finance 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 InvoiceController(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!');
};
}]);
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><br>
<button class="btn" ng-click="invoice.pay()">Pay</button>
</div>
</div>
我们将convertCurrency函数和现有货币的定义移动到新文件finance2.js中。但是控制器如何保持现在分离的功能?
这是依赖注入发挥作用的地方。依赖注入(DI)是一种软件设计模式,它处理对象和函数如何创建以及如何获得它们的依赖。 AngularJS中的所有内容(指令,过滤器,控制器,服务,...)都是使用依赖注入创建和连接的。在AngularJS中,DI容器称为注入器。
要使用DI,需要一个地方,所有应该一起工作的东西都注册。在AngularJS中,这是模块的目的。当AngularJS启动时,它将使用具有由ng-app指令定义的名称的模块配置,包括该模块所依赖的所有模块的配置。
在上面的示例中:模板包含指令ng-app =“invoice2”。这告诉AngularJS使用invoice2模块作为应用程序的主模块。代码片段angular.module('invoice2',['finance2'])指定invoice2模块依赖于finance2模块。通过这个,AngularJS使用InvoiceController以及currencyConverter服务。
现在AngularJS知道应用程序的所有部分,它需要创建它们。在上一节中,我们看到控制器是使用构造函数创建的。对于服务,有多种方式指定如何创建它们(请参阅服务指南)。在上面的例子中,我们使用一个匿名函数作为currencyConverter服务的工厂函数。此函数应返回currencyConverter服务实例。
回到最初的问题:InvoiceController如何获得对currencyConverter函数的引用?在AngularJS中,这是通过简单地定义参数的构造函数。这样,注入器能够以正确的顺序创建对象,并且将先前创建的对象传递到依赖于它们的对象的工厂中。在我们的示例中,InvoiceController有一个名为currencyConverter的参数。通过这个,AngularJS知道控制器和服务之间的依赖关系,并以服务实例作为参数来调用控制器。
在上一节和本节之间的示例中,最后一件事情是改变了,现在我们将一个数组传递给module.controller函数,而不是一个简单的函数。数组首先包含控制器需要的服务依赖关系的名称。数组中的最后一个条目是控制器构造函数。 AngularJS使用这个数组语法来定义依赖关系,以便DI也可以在缩小代码后工作,这很可能会将控制器构造函数的参数名称重新命名为更短的。
访问后端
让我们通过从Yahoo Finance API获取汇率来完成我们的示例。 以下示例说明如何使用AngularJS完成此操作:
invoice3
angular.module('invoice3', ['finance3'])
.controller('InvoiceController', ['currencyConverter', function InvoiceController(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';
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.get(url).then(function(response) {
var newUsdToForeignRates = {};
angular.forEach(response.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
};
}]);
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><br>
<button class="btn" ng-click="invoice.pay()">Pay</button>
</div>
</div>
我们的financeConverter服务的财务模块现在使用$ http,AngularJS提供的内置服务访问服务器后端。 $ http是XMLHttpRequest和JSONP传输的包装器。
Angular开发者指南(二)概念概述的更多相关文章
- Angular开发者指南(一)入门介绍
什么是Angular AngularJS是动态Web应用程序的结构框架. 它允许您使用HTML作为模板语言,并允许您扩展HTML的语法以清晰,简洁地表达应用程序的组件.AngularJS的数据绑定和依 ...
- Angular开发者指南(七)依赖注入
依赖注入 依赖注入(DI)是一种软件设计模式,处理组件如何获取其依赖关系. AngularJS注入器子系统负责创建组件,解析它们的依赖关系,并根据请求将它们提供给其他组件. 使用依赖注入 DI遍布An ...
- Angular开发者指南(六)作用域
什么是作用域? 作用域是引用应用程序模型的对象. 它是表达式的执行上下文. 作用域以层次结构排列,模仿应用程序的DOM结构,它可以观察表达式和传播事件. 作用域的特征 Scope提供API($watc ...
- Angular开发者指南(五)服务
服务 AngularJS服务是使用依赖注入(DI)连接在一起的可替代对象. 可以使用服务在整个应用程式中整理和分享程式码. AngularJS服务有: 延迟初始化 - AngularJS只在应用程序组 ...
- Angular开发者指南(四)控制器
了解控制器controller 在AngularJS中,Controller由JavaScript构造函数定义,用于扩充AngularJS Scope. 当控制器通过ng-controller指令连接 ...
- Angular开发者指南(三)数据绑定
数据绑定 AngularJS应用程序中的数据绑定是模型和视图组件之间的数据的自动同步. AngularJS实现数据绑定的方式可以将模型视为应用程序中的单一来源. 视图是模型在任何时候的投影. 当模型更 ...
- 成为优秀Angular开发者所需要学习的19件事
一款to-do app基本等同于前端开发的"Hello world".虽然涵盖了创建应用程序的CRUD方面,但它通常只涉及那些框架或库也能做到的皮毛而已. Angular看起来似乎 ...
- Cocos引擎开发者指南(1-5)
Cocos引擎开发者指南 英文原版:http://www.cocos2d-x.org/docs/programmers-guide/1/ 中午翻译:http://www.cocos.com/doc/t ...
- AngularJS概念概述和第一个使用例子
点击查看AngularJS系列目录 转载请注明出处:http://www.cnblogs.com/leosx/ 概念概述 本节使用一个简单的例子简要介绍了AngularJS的重要组成部分. 概念 描述 ...
随机推荐
- MySQL表的几个简单查询语句
1. 创建数据库CREATE DATABASE database-name 2. 删除数据库drop database dbname 3. 创建新表create table tabname(co ...
- CodeForces (字符串从字母a开始删除k个字母)
You are given a string s consisting of n lowercase Latin letters. Polycarp wants to remove exactly k ...
- 给adobe acrobat reader 添加图片注释
首先展示一下 我添加注释的结果, 下面是我的做法: 在Adobe Acrobat 中打开Sample.pdf文档,点开文档右边的“工具”-“内容”-选择“编辑对象”,鼠标光标变成实心箭头+右下角小方 ...
- windows 10 远程连接出现CredSSP加密Oracle修正错误
以下方法只受用于windows专业版或者企业版 . 解决方法: 运行 gpedit.msc 本地组策略: 计算机配置>管理模板>系统>凭据分配>加密Oracle修正 选择启用并 ...
- PCB布局注意事项
PCB布局注意事项 1.实现统一功能电路模块中的元件应采用就近集中原则,同时数字电路和模拟电路分开; 2.定位孔.标准孔等非安装孔周围1.27mm 内不得贴装元.器件,螺钉等安装孔周围3.5mm( ...
- Kali桥接模式下配置动态ip
以管理员身份运行虚拟机 打开 控制面板-->网络和Internet-->更改适配器 在虚拟机处桥接到这个WLAN2 点击 编辑-->编辑虚拟网卡 没有网卡就点上图的添加网络作为桥接网 ...
- java设计模式--六大原则
一.单一职责原则 单一职责原则:就一个类而言,应该仅有一个引起它变化的原因.通俗来说,就是互相不相关的属性和方法不要放在一个类中,就好比之前简单工厂模式中介绍的那样,客户端(Customer)应该与工 ...
- for-each用法误区(不能改变数组元素值)
代码例程: /** * 数据加密传输 */ import java.util.Scanner; public class secretPass { public static void m ...
- PHP静态方法和普通方法的区别
<?php header('content-type:text/html;charset=utf-8'); /* 普通方法,存放类内,只有一份 静态方法,也是存放于类内,只有一份 区别在于:普通 ...
- //使用PDO连接mysql数据库
<?php //使用PDO连接mysql数据库 class pdo_con{ var $dsn = 'mysql:dbname=test; host:127.0.0.1'; va ...