Angular概念纵览
Conceptual Overview
- Template(模板): HTML with additional markup (就是增加了新的标记的HTML)
- Directive(指令): extend HTML with custom attributes and elements (给HTML增加自定义属性和元素)
- Model(模型): the data shown to the user in the view and with which the user interacts (与用户交互的视图背后的数据)
- Scope(作用域): context where the model is stored so that controllers, directives and expressions can access it (存储模型的上下文,可供控制器,指令和表达式调用)
- Expressions(表达式): access variables and functions from the scope (能从作用域里访问变量和函数)
- Compiler(编译器): parses the template and instantiates directives and expressions (编译模板和初始化指令和表达式)
- Filter(过滤器): formats the value of an expression for display to the user (“美化”表达式展示给用户的数据)
- View(视图): what the user sees (the DOM) (用户看到的DOM)
- Data Binding(数据绑定): sync data between the model and the view (模型和视图之间双向的数据同步)
- Controller(控制器): the business logic behind views (视图背后的业务逻辑所在)
- Dependency Injection(依赖注入): Creates and wires objects and functions (创建和串起对象和方法)
- Injector(注入器): dependency injection container (依赖注入容器)
- Module(模块): a container for the different parts of an app including controllers, services, filters, directives which configures the injector. (控制器,服务,过滤器,指令的容器)
- Service(服务): reusable business logic independent of views (独立于视图的可复用业务逻辑)
(官网对Angular里的概念做出的最原味的解释。)
(先贴地址:https://code.angularjs.org/1.3.15/docs/guide/concepts)
A first example: Data binding
<div ng-app ng-init="qty=1;cost=2">
<b>Invoice:</b> <div>
<label>Quantity(数量):</label> <input type="number" min="0" ng-model="qty">
</div>
<div>
<label>Costs(单价):</label> <input type="number" min="0" ng-model="cost">
</div>
<div>
<b>Total(总价):</b> {{qty * cost | currency}}
</div>
</div>
This looks like normal HTML, with some new markup. In Angular, a file like this is called a “template”. When Angular starts your application, it parses and processes this new markup from the template using the so-called “compiler”. The loaded, transformed and rendered DOM is then called the “view”.
The first kind of new markup are the so-called “directives”. They apply special behavior to attributes or elements in the HTML.
The second kind of new markup are the double curly braces {{ expression | filter }}: when the compiler encounters this markup, it will replace it with the evaluated value of the markup. An “expression” in a template is a JavaScript-like code snippet that allows to read and write variables. Note that those variables are not global variables. Just like variables in a JavaScript function live in a scope, Angular provides a “scope” for the variables accessible to expressions. The values that are stored in variables on the scope are referred to as the “model”.
上面的代码看着就是一般的HTML嘛,只不过多了些新的标记。在Angular里,这种带新标记的HTML,称为模板(template)。当Angular启动你的应用时,它就会使用它自己的“编译器(compiler)”解析并处理模板中这种新的标记。而经过加载,转换和渲染之后的DOM,就称为视图(view)。
新的标记有2种:
- 第1种叫指令(directive)。它可以把特殊的行为附给属性或者元素。
- 第2种是(大名鼎鼎的)双大括号。当编译器遇到它的时候,会把它换成算好的值。模板中的表达式,就是一段可以读写变量的JavaScript代码片段。注意,这里的变量不是全局变量。就像函数里的变量只在函数里有效一样,这些变量也有自己的作用域。Angular提供一个作用域(scope)的概念,用来存放可供表达式调用的变量。(上面就是在介绍表达式要调用变量嘛,不然解释变量是谁家的变量干嘛)能够从作用域下调出来的变量,我们就统称为模型(model)。(有没有感觉MVC里的M和V很形象地展现了?)
(图还是看看好,万一理解更深刻了呢)
注意:
Custom directives to access the DOM: In Angular, the only place where an application should access the DOM is within directives. This is important because artifacts that access the DOM are hard to test. If you need to access the DOM directly, you should write a custom directive for this.
一定要自定义指令去访问DOM啊!:在Angular里,一个应用访问DOM的唯一位置,应该限定在自定义指令中。为啥呢?因为其他途径访问DOM的话,Angular恐怕会检测不到(你有想过维持双向数据绑定之类的有关MVC和谐发展的事有多辛苦吗?)。所以呢,如果你要访问DOM,先自定义一个指令吧。
A filter formats the value of an expression for display to the user. In the example above, the filter currency formats a number into an output that looks like money.
The important thing in the example is that Angular provides live bindings: Whenever the input values change, the value of the expressions are automatically recalculated and the DOM is updated with their values. The concept behind this is “two-way data binding”.
一个过滤器可以把表达式所表达的内容格式化之后展示给用户。上面例子里,过滤器currency把一个数字格式化成了钱钱的样子。
Angular的犀利之处在于它提供动态绑定:
只要数据变了,表达式就会自动被重新计算,再通过更新DOM来展示出来。这就是(传说中的)“双向数据绑定”的概念。
Adding UI logic: Controllers
html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="../../angularjs1.3.15/angular.min.1.3.15.js"></script>
<script src="invoice1.js"></script>
<title>Adding UI logic: Controllers</title>
</head>
<body>
<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>
</body>
</html>
JavaScript (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!");
};
});
What changed?
First, there is a new JavaScript file that contains a so-called “controller”. More exactly, the file contains a constructor function that creates the actual controller instance. The purpose of controllers is to expose variables and functionality to expressions and directives.
Besides the new file that contains the controller code, we also added an ng-controller directive to the HTML. This directive tells Angular that the new InvoiceController is responsible for the element with the directive and all the element’s children. The syntax InvoiceController as invoice tells Angular to instantiate the controller and save it in the variable invoice in the current scope.
这一次有什么改变呢?
首先,这次创建了个新JavaScript文件,其中包含一个所谓的“控制器”。也就是说,这个JavaScript文件包含一个构造函数,而正是这个构造函数会创建一个真正的控制器实例。控制器的目的就是把变量和方法暴露给表达式和指令来使用。
除了增加控制器代码的文件外,我们还在HTML理添加了一个ng-controller指令。这个指令告诉Angular,InvoiceController负责为这个元素和它的子元素里的指令服务(上面不是说了,控制器给表达式和指令提供变量和方法么)。InvoiceController as invoice这个语法同时还告诉Angular,创建一个InvoiceController的实例,并且在当前作用域里存储它的时候命名为invoice。
We also changed all expressions in the page to read and write variables within that controller instance by prefixing them with invoice. The possible currencies are defined in the controller and added to the template using ng-repeat. As the controller contains a total function we are also able to bind the result of that function to the DOM using {{invoice.total(...)}}.
Again, this binding is live, i.e. the DOM will be automatically updated whenever the result of the function changes. The button to pay the invoice uses the directive ngClick. This will evaluate the corresponding expression whenever the button is clicked.
其次,我们把所有表达式里用到的变量,都添加了控制器实例的前缀,这样变量就都是从控制器里获取了。例子里使用控制器中的变量和方法的有:
- ng-repeat把currencies(介是一个array。你看,repeat,是吧)展示了出来;
- {{invoice.total(c) | currency:c}}调用了方法。
再次,这些绑定都是动态的,DOM会在函数结果变动之后自动更新。写着pay的按钮使用了ngClick指令,这个指令会在按钮被点击之后执行指定的函数。
(图还是看看好,万一真看懂了呢)
View-independent business logic: Services
Right now, the InvoiceController contains all logic of our example. When the application grows, it is good practice to move view-independent logic from the controller into a service, so it can be reused by other parts of the application as well. Later on, we could also change that service to load the exchange rates from the web.
独立于界面展示的业务逻辑:服务
现在,InvoiceController这个控制器包含所有的逻辑处理。随着应用越来越大,最好是把跟界面展示无关的逻辑放进服务(service)里,从而在应用的其他部分需要的时候,可以重复使用。
Let’s refactor our example and move the currency conversion into a service in another file:(重构代码,添加服务)
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="../../angularjs1.3.15/angular.min.1.3.15.js"></script>
<script src="invoice2.js"></script>
<script src="finance2.js"></script>
<title>Adding Service</title>
</head>
<body>
<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>
</body>
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!");
};
}]);
What changed?
We moved the convertCurrency function and the definition of the existing currencies into the new file finance2.js. But how does the controller get a hold of the now separated function?
我们把一些函数和变量的定义移动到了finance2.js里。但是,控制器怎么去获取它们呢?(都跑别的文件里了的说)
This is where “Dependency Injection” comes into play. Dependency Injection (DI) is a software design pattern that deals with how objects and functions get created and how they get a hold of their dependencies. Everything within Angular (directives, filters, controllers, services, ...) is created and wired using dependency injection. Within Angular, the DI container is called the “injector”.
这个时候就轮到“依赖注入”出场了。依赖注入是一种设计模式,它控制对象和方法的创建,以及它们如何获取它们的依赖项。Angular中的所有内容(指令,过滤器,控制器,服务,…)都是使用依赖注入创建并串起来的。在Angular里,依赖注入的容器叫做“注入器”。
To use DI, there needs to be a place where all the things that should work together are registered. In Angular, this is the purpose of the so-called “modules”. When Angular starts, it will use the configuration of the module with the name defined by the ng-app directive including the configuration of all modules that this module depends on.
要使用DI,首先要有个地方把所有要用到的组件登记一下(不然Angular怎么给你创建,供你使用?)。在Angular里,完成这个工作的家伙叫做“模块”。当Angular启动的时候,它会根据ng-app找到入口模块并去载配置,也包括入口模块所依赖的其他模块的配置。(废话,不加载怎么玩?)
In the example above: The template contains the directive ng-app=”invoice2”. This tells Angular to use the invoice2 module as the main module for the application. The code snippet angular.module(‘invoice2’, [‘finance2’]) specifies that the invoice2 module depends on the finance2 module. By this, Angular uses the InvoiceController as well as the currencyConverter service.
在上例中,模板里包含这样一个指令ng-app=”invoice2”。这个指令告诉Angular去用invoice2这个模块作为这个应用的主模块。angular.module(‘invoice2’, [‘finance2’])则指明invoice2依赖于finance2这个模块。由此,Angular使用InvoiceController这个控制器和currencyConverter这个服务。
Now that Angular knows of all the parts of the application, it needs to create them. In the previous section, we saw that controllers are created using a factory function. For services there are multiple ways to define their factory. In the example above, we are using a function that returns the currencyConverter function as the factory for the service.
Angular在前面提到的注入之后,对应用的每一部分都知道怎么加载,它现在就要创建这些部分了。前面的例子里我们看到,控制器是被一个工厂函数创建的,而要加载服务,我们有很多种方法去定义它们的加载工厂函数。上例中,我们(这里我实在翻不下去了)
Back to the initial question: How does the InvoiceController get a reference to the currencyConverter function? In Angular, this is done by simply defining arguments on the constructor function. With this, the injector is able to create the objects in the right order and pass the previous created objects into the factories of the objects that depend on them. In our example, the InvoiceController has an argument named currencyConverter. By this, Angular knows about the dependency between the controller and the service and calls the controller with the service instance as argument.
那么问题又来了:我们怎么在InvoiceController里拿currencyConverter(的引用)?(毕竟这次不是在自己内部,随便调用,而是依赖注入进来的,注入完怎么用?)在Angular里,这个很简单的,只要在构造函数上加个参数就可以了。只要你敢加参,注入器就敢按套路给你把全部依赖的对象创建出来,并传递给依赖它们的对象。我们的例子里,InvoiceController就有个参数叫currencyConverter。你这么一传,Angular就知道这个控制器是依赖那个服务的,它调用这个控制器的时候,就把依赖的服务(的实例)作为参数传了进去。
The last thing that changed in the example between the previous section and this section is that we now pass an array to the module.controller function, instead of a plain function. The array first contains the names of the service dependencies that the controller needs. The last entry in the array is the controller constructor function. Angular uses this array syntax to define the dependencies so that the DI also works after minifying the code, which will most probably rename the argument name of the controller constructor function to something shorter like a.
我再说最后一个这个例子跟上个例子的不同。那就是这次我们把一个array传给了module.controller,而不是只传一个函数。为啥呢?因为这个array里面前面的东西,都是最后这个控制器所依赖的服务的名字。只有array最后一项才是真正的构造函数。Angular这样定义依赖的关系,就可以在代码被压缩之后,还可以正常使用依赖注入。毕竟,压缩后的代码,参数名都变成了a啊b啊c啊什么的,让依赖注入去注入这些乱七八糟的东西,它也做不到啊。(可你用string这种东西注入,显然压缩之后,值也不会变的)
(上面这段可以就着这个图来看)
Angular概念纵览的更多相关文章
- Angular系列一:Angular程序架构
Angular程序架构 Angular程序架构 组件:一段带有业务逻辑和数据的Html服务:用来封装可重用的业务逻辑指令:允许你向Html元素添加自定义行为模块: 环境搭建 安装nodeJs安装好no ...
- AngularJS:何时应该使用Directive、Controller、Service?【新手必看】
(这篇文章你们一定要看,尤其初学的人,好吗亲?) 大漠穷秋 译 AngularJS是一款非常强大的前端MVC框架.同时,它也引入了相当多的概念,这些概念我们可能不是太熟悉.(译者注:老外真谦虚,我大天 ...
- AngularJS:何时应该使用Directive、Controller、Service?
AngularJS:何时应该使用Directive.Controller.Service? (这篇文章你们一定要看,尤其初学的人,好吗亲?) 大漠穷秋 译 AngularJS是一款非常强大的前端MVC ...
- 何时应该使用Directive、Controller、Service?
AngularJS:何时应该使用Directive.Controller.Service? 大漠穷秋 译 AngularJS是一款非常强大的前端MVC框架.同时,它也引入了相当多的概念,这些概念我们可 ...
- AngularJs学习——何时应该使用Directive、Controller、Service?
翻译:大漠穷秋 原文链接:http://kirkbushell.me/when-to-use-directives-controllers-or-services-in-angular/ 一.简述 A ...
- [转]AngularJS:何时应该使用Directive、Controller、Service?
AngularJS是一款非常强大的前端MVC框架.同时,它也引入了相当多的概念,这些概念我们可能不是太熟悉.(译者注:老外真谦虚,我大天朝的码农对这些概念那是相当熟悉啊!)这些概念有: Directi ...
- MVC、MVP、MVVM、Angular.js、Knockout.js、Backbone.js、React.js、Ember.js、Avalon.js、Vue.js 概念摘录
注:文章内容都是摘录性文字,自己阅读的一些笔记,方便日后查看. MVC MVC(Model-View-Controller),M 是指业务模型,V 是指用户界面,C 则是控制器,使用 MVC 的目的是 ...
- 走进AngularJs(一)angular基本概念的认识与实战
一.前言 前端技术的发展是如此之快,各种优秀技术.优秀框架的出现简直让人目不暇接,作为一名业界新秀,紧跟时代潮流,学习掌握新知识自然是不敢怠慢.当听到AngularJs这个名字并知道是google在维 ...
- Angular 核心概念
module(模块) 作用 通过模块对页面进行业务上的划分,根据不同的功能划分不同的模块. 将重复使用的指令或者过滤器之类的代码做成模块,方便复用 注意必须指定第二个参数,否则变成找到已经定义的模块 ...
随机推荐
- 循序渐进Python3(八) -- 0 -- 初识socket
socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Un ...
- cell嵌套UIWebView遇到的几个问题
一.防止死循环问题 方法一:使用动画块 [self.myTableView beginUpdates];[self.myTableView endUpdates]; 在下面的代 ...
- npm install 出现UNABLE_TO_GET_ISSUER_CERT_LOCALLY
解决方式 As a workaround you can turn ssl checking off in your .npmrc 执行 npm config set strict-ssl false ...
- nullcon HackIM 2016 -- Programming Question 5
Dont blink your Eyes, you might miss it. But the fatigue and exhaustion rules out any logic, any wil ...
- [测]jieba分词
import jieba import os import jieba.analyse with open('src.txt', 'r') as file: data = file.read() se ...
- Altium Designer15 卡在登陆界面解决办法:
Altium Designer15 卡在登陆界面解决办法: 在我的电脑系统盘中找到下面目录(注:如果看不到,需要取消隐藏文件选项.) C:\Documents and Settings\Adminis ...
- Android(Logcat、Monitors)
刚学习Android 的时候总喜欢输出"Hello Word"这样的信息来判断是不是执行了某个方法,最初连Android Studio控制台.断点这些在哪里都要找好久,现在好了多点 ...
- Tcc学习笔记(二) 安装和配置
1.下载和编译 去repo.or.cz/tinycc.git下载最新的snapshot压缩包, 或者用git命令下载: git clone git://repo.or.cz/tinycc.git . ...
- Button四角有弧度及按下显示不同的颜色
一般的button都是矩形或者正方形,但为了显示不同的效果,让界面更美化,可以对其进行处理!!! 1.四角有弧度的button 2.按下button显示不同的颜色 实现步骤: 首先在drawable文 ...
- 帮助对@Repository注解的理解
定义(来自Martin Fowler的<企业应用架构模式>): Mediates between the domain and data mapping layers using a co ...