Angular(二)
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(二)
angularjs第二章 自定义指令 scope 控制器 AngularJS控制器控制AngularJS应用程序的数据,是常规的JavaScript对象. ng-controller指令就是用来定义应 ...
- Angular(二)
<!DOCTYPE html> <html lang="en" ng-app='myApp'> <head> <meta charset= ...
- Angular(二) - 组件Component
1. 组件Component示例 2. Component常用的几个选项 3. Component全部的选项 3.1 继承自@Directive装饰器的选项 3.2 @Component自己特有的选项 ...
- 【Angular专题】——(1)Angular,孤傲的变革者
目录 一. 漫谈Angular 二. 如果你还在使用Angularjs 三. 我计划这样学习Angular技术栈 一. 漫谈Angular Angular,来自Google的前端SPA框架,与Reac ...
- angular编译机制
转载https://segmentfault.com/a/1190000011562077 Angular编译机制 前言 http://www.cnblogs.com/ztwBlog/p/620975 ...
- Angular 7开发环境配置
目录 前言 一.搭建项目 1.安装Angular CLI 2.创建项目 3.集成Element Angular 二.设置路由 1.创建路由模块 2.导入.导出RouterModule类 3 ...
- AngularJS的相关应用
一.[AngularJS常用指令] 1.ng-app:声明Angular所管辖的区域.一般写在body或html上,原则上一个页面只有一个: <body ng- ...
- angular服务二
angular服务 $http 实现客户端与服务器端异步请求 get方式 test.html <!DOCTYPE html> <html lang="en"> ...
- angular学习笔记(二十九)-$q服务
angular中的$q是用来处理异步的(主要当然是http交互啦~). $q采用的是promise式的异步编程.什么是promise异步编程呢? 异步编程最重要的核心就是回调,因为有回调函数,所以才构 ...
- Angular组件——组件生命周期(二)
一.view钩子 view钩子有2个,ngAfterViewInit和ngAfterViewChecked钩子. 1.实现ngAfterViewInit和ngAfterViewChecked钩子时注意 ...
随机推荐
- GCPC 2013_A Boggle DFS+字典树 CSU 1457
上周比赛的题目,由于那个B题被神编译器的优化功能给卡了,就没动过这个题,其实就是个字典树嘛.当然,由于要在Boggle矩阵里得到初始序列,我还一度有点虚,不知道是用BFS还是DFS,最后发现DFS要好 ...
- DispatcherServlet继承体系
GenericServlet implements Servlet, ServletConfig, java.io.Serializable | HttpServlet ...
- PTA 天梯赛 L1
L1-002 打印沙漏 细节:就是在 (i>j&&i+j<r+1) 这个区间里才有空格,然后就是 for 循环 for(r=1; ;r+=2) 条件不满足之后还会再 ...
- html_js
<!-- js的特点:别名脚本 -由浏览器内置的JavaScript引擎执行代码. -解析执行:事先不编译,逐行执行 -面向对象:内置大量的现成对象 适宜: -客户端的数据计算:不需要保存和提交 ...
- fastreport小入门
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- CentOS 7.3 下部署基于 Node.js的微信小程序商城
本文档为微信小程序商城NideShop项目的安装部署教程,欢迎star NideShop商城api服务:https://github.com/tumobi/nideshop NideShop微信小程序 ...
- win10使用笔记本自带显卡GUP安装CUDA,版本问题
1.GPU算力问题 查询:win+r, GPU:GeForce GTX 850m,算力5.0,还可以跑得起来深度项目 2.我们需要查看NVIDIA驱动版本,才能安装合适的CUDA版本. 在C:\Pro ...
- CommandNotFoundError: No command 'conda conda'.
出现情形 当前conda版本:4.6.11 当使用git bash,无论是在vscode中,还是在桌面上打开bash,都会出现这个错误.但是在cmd中,就可以识别conda命令. 解决 该错误只在4. ...
- 2. laravel 5.5 学习 过程中 遇到问题 的 链接
关于 laravel 5.5 的文档 网络上已经太多 就不些太多重复的话了 在以后的 工作 中遇到问题的 查询到的解决方案 或者 相关文档将会具体写在这里 laravel 5.5 中文文档 https ...
- Java 面向对象概述原理: 多态、Object类,转型(8)
Java 面向对象概述原理: 多态.Object类,转型(8) http://docs.oracle.com/javase/tutorial/java/IandI/override.html Java ...