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开发者指南(二)概念概述的更多相关文章

  1. Angular开发者指南(一)入门介绍

    什么是Angular AngularJS是动态Web应用程序的结构框架. 它允许您使用HTML作为模板语言,并允许您扩展HTML的语法以清晰,简洁地表达应用程序的组件.AngularJS的数据绑定和依 ...

  2. Angular开发者指南(七)依赖注入

    依赖注入 依赖注入(DI)是一种软件设计模式,处理组件如何获取其依赖关系. AngularJS注入器子系统负责创建组件,解析它们的依赖关系,并根据请求将它们提供给其他组件. 使用依赖注入 DI遍布An ...

  3. Angular开发者指南(六)作用域

    什么是作用域? 作用域是引用应用程序模型的对象. 它是表达式的执行上下文. 作用域以层次结构排列,模仿应用程序的DOM结构,它可以观察表达式和传播事件. 作用域的特征 Scope提供API($watc ...

  4. Angular开发者指南(五)服务

    服务 AngularJS服务是使用依赖注入(DI)连接在一起的可替代对象. 可以使用服务在整个应用程式中整理和分享程式码. AngularJS服务有: 延迟初始化 - AngularJS只在应用程序组 ...

  5. Angular开发者指南(四)控制器

    了解控制器controller 在AngularJS中,Controller由JavaScript构造函数定义,用于扩充AngularJS Scope. 当控制器通过ng-controller指令连接 ...

  6. Angular开发者指南(三)数据绑定

    数据绑定 AngularJS应用程序中的数据绑定是模型和视图组件之间的数据的自动同步. AngularJS实现数据绑定的方式可以将模型视为应用程序中的单一来源. 视图是模型在任何时候的投影. 当模型更 ...

  7. 成为优秀Angular开发者所需要学习的19件事

    一款to-do app基本等同于前端开发的"Hello world".虽然涵盖了创建应用程序的CRUD方面,但它通常只涉及那些框架或库也能做到的皮毛而已. Angular看起来似乎 ...

  8. Cocos引擎开发者指南(1-5)

    Cocos引擎开发者指南 英文原版:http://www.cocos2d-x.org/docs/programmers-guide/1/ 中午翻译:http://www.cocos.com/doc/t ...

  9. AngularJS概念概述和第一个使用例子

    点击查看AngularJS系列目录 转载请注明出处:http://www.cnblogs.com/leosx/ 概念概述 本节使用一个简单的例子简要介绍了AngularJS的重要组成部分. 概念 描述 ...

随机推荐

  1. [Qt5] QSlider设置步长

    这是一个小问题,就是QSlider是一个滑动条控件,既然是个滑动条控件,就会想要用鼠标滚轮或者鼠标去移动它来实现某些功能,但是呢,我能说这个控件的一个属性函数设置也是比较奇怪的,它设置步长的函数有 s ...

  2. Spring框架-IOC和AOP

    IOC:它并不是一种技术实现,而是一种设计思想.在任何一个有实际开发意义的程序项目中,我们会使用很多类来描述它们特有的功能,并且通过类与类之间的相互协作来完成特定的业务逻辑.这个时候,每个类都需要负责 ...

  3. try,catch,finally尝试(一个程序块多个catch)

    曾学过c++,但是对这些异常捕捉不是很了解,通过别的编程语言了解 public class newclass { public static void main(String[] args) { tr ...

  4. springBoot中的邮件发送

    1. 添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  5. oracle 向表中插入BLOB类型数据

    提示: 待插入图片必须保存到oracle主机路径上. 步骤: 1.SYSDBA权限用户创建图片所在目录 CREATE OR REPLACE DIRECTORY TEST_DIR AS 'C:\Pict ...

  6. 十五、Numpy-科学计算基础库

    Numpy:          NumPy(Numerical Python) 是科学计算基础库,提供大量科学计算相关功能,比如数据统计,随机数生成等.其提供最核心类型为多维数组类型(ndarray) ...

  7. 201771010123汪慧和《面向对象程序设计JAVA》第六周实验总结

    一.理论部分: 1.继承 用已有类来构建新类的一种机制.当定义了一个新类继承了一个类时,这个新类就继承了这个类的方法和域,同时在新类中添加新的方法和域以适应新的情况. 2.类.超类.子类 (1)类继承 ...

  8. pycharm调试、设置汇总

    目录: 1.pycharm中不能run 2.pycharm基本调试操作 3.pycharm使用技巧 4.pycharm Error running draft: Cannot run program ...

  9. JavaScript学习总结(三)

    在学习完了基本的内容之后,我们来学习一下JavaScript中的对象部分以及如何自定义对象的问题. String对象 创建字符串的方式共有两种: 方式1:new String("内容&quo ...

  10. UVA 10273

    我是用暴力过的,虽然网上说刘汝佳出的这道题考的是堆,我不太懂,..用暴力时间复杂度高一些,但是一样能过 所要注意的就是周期问题,因为只要同时存在某一天超过一头牛产奶量最小,就不会杀牛,而每头牛的周期和 ...