@Component({
selector: 'talk-app',
viewInjector: [TalksAppBackend] // registered in the root component, so it can be injected into any component in the app.
})
class Application {
}
@Component({
selector: 'talk-list'
})
class TalkList {
constructor(backend:TalksAppBackend) {
this.talks = backend.fetchTalks();
}
}
原文地址: http://victorsavkin.com/post/118372404541/the-core-concepts-of-angular-2
让我们来构建一个程序
![](http://www.kittencup.com/images/2015-07-17-Angular 2的核心概念/feed.png)
组件(Component)
Angular 2的应用是由一系列的组件构成的(ui element、route..),应用始终有一个包含其他组件的根组件,换句话每个angualr2应用都有一个组件树,这个应用程序可能是这样的:
![](http://www.kittencup.com/images/2015-07-17-Angular 2的核心概念/a.png)
Application是一个根组件,Filters组件具有speaker输入框和过滤按钮,下面有一系列的talks,及每一个talk-cmp
属性和事件绑定
一个组件具有的属性和事件绑定,这些内容在组件的decorator定义。
数据通过组件上的属性绑定流入组件,数据通过组件上的事件绑定流出组件
![](http://www.kittencup.com/images/2015-07-17-Angular 2的核心概念/b.png)
当你在应用程序中实例化一个组件则可以通过公共API使用属性和事件绑定
视图(View)
一个组件有一个视图,描述了在页面上怎么呈现组件
Angular 2遵循web平台标准,因此组件视图元素会在Shadow DOM内创建,如果你的浏览器不支持Shadow DOM,Angular会模拟Shadow DOM.
一个视图需要知道两件事情:模板本身及模板中可使用的指令。如在上面的例子中,你可以在外部定义模板,使用templateUrl,或内联模板template。
生命周期(LIFECYCLE)
组件有一个定义良好的生命周期可以利用(onChange、onInit、onCheck、onAllChangesDone)。该TalkCmp组件不订阅任何生命周期事件,但一些其他组件可以。例如,该组件发生改变时会触发起change事件。
注入(INJECTABLES)
一个组件可以包含一个注入对象列表,它的子组件可能也需要注入
在这个例子中,我们在根组件中声明ConfAppBackend,和Logger,这使得它们在整个应用程序可用,TalksCmp组件注入ConfAppBackend,我将在本文的第二部分详细讨论依赖注入
HOST元素(HOST ELEMENT)
要将Angular组件渲染成DOM中的某种东西,你需要在Angular组件中结合一个DOM元素,我们称这些叫host元素。
一个组件可以用以下方式于其host DOM元素进行交互
例如,组件可以使用host事件监听输入,对输入值进行处理及将其存储在一个字段中,angular会于DOM同步已存储的值
请注意,我真得直接与DOM交互。Angular2旨在提供一个更高层次的API,所以在原生平台(native platform),DOM,只会反映angular应用程序的状态。
这里几个原因非常有用:
有时候,你只需要直接与DOM进行交互。Angular 2提供了这样的API,但我们的希望是,你很少会需要使用它们。
组件是自描述性(COMPONENTS ARE SELF-DESCRIBING)
我所列出的组件构成.
在Angular2中所有的这些组件都具有自描述性,所以组件的注释(annotations)包含它们的实例所需要的所有信息。这是非常重要的。
这意味着任何组件可以引导作为应用程序,它并不需要任何特殊的方式,此外,任何组件可以被加载到一个router-outlet(ng-view)。因此,您可以编写一个应用程序组件,可被引导(bootstrap),加载路由(route),或直接用于其他组件,这将导致更少的API来学习。同时也让更多的组件可重用。
指令是什么?(WHAT ABOUT DIRECTIVES?)
如果您熟悉angular 1,你一定想知道“指令发生了什么变化”。
其实指令还在Angular 2中,组件只是指令中的最重要的一种,但不是唯一的指令类型,一个组件是一个指令,一个视图,你仍然可以编写一个没有视图的装饰器风格(decorator-style)的指令
![](http://www.kittencup.com/images/2015-07-17-Angular 2的核心概念/c.png)
依赖注入(DEPENDENCY INJECTION)
让我们来谈论Angular 的另一个重要基石,依赖注入。
依赖注入背后的想法很简单,如果有一个依赖于一个服务的组件。您无需自己创建服务并提供给组件,相反,你可以在构造函数中申请该服务,框架将会自动提供给你该服务,通过这样做,你可以依赖接口,而不是具体类型,这将导致更多的代码解耦,使可测试性和其他更好的事情。
![](http://www.kittencup.com/images/2015-07-17-Angular 2的核心概念/d.png)
Angular 2配备了依赖注入模块,看它如何被使用,让我们来看看下面的组件,该指令渲染一个talks的列表
我们模拟一个简单的服务,会提供给我们数据
我们如何使用这项服务?一种方法是在我们的组件创建该服务的一个实例。
这是一个不错的演示应用程序,但对于实际应用并不好,在实际应用中TalksAppBackend将不只是返回对象的数组,它会发出HTTP请求来获取数据,这意味着在单元测试中这个组件会创建真实的http-requrest(这不是一个好主意),这个问题是由已经耦合TalkList到TalksAppBackend这一事实引起的
我们可以通过注入一个实例TalksAppBackend到构造函数解决这个问题,所以我们可以把它在测试中轻易更换,就像这样:
这告诉了angular TalksList 依赖于TalksAppBackend,现在我们需要告诉Angular如果创建依赖,我们可以为此组件通过添加viewInjector属性
该TalksAppBackend服务必须在TalkList组件或其祖先指定,所以,如果你喜欢写用Angular 1编写应用方式,你可以在根组件配置你的所有注射服务
(单一API)SINGLE API
Angular 1和Angular 2 都配备了依赖注入的模块,但在Angular 1,我们有几个API来注入依赖到指令:有的对象是按位置(例如,元素)注入,有的按名称,这有点混乱。Angular 2提供了注入依赖的单一的API,他们全部在组件的constrocutor中注入。
例如,此组件注入TalksAppBackend(这很可能是一个单列),和一个ElementRef,这是唯一的每个组件的一个实例。
所以我们通过相同的API将全局和局部依赖注入到组件中。此外,组件可以使用相同API注入到其他组件中
依赖注入是你可能马上看不到的好处之一,但当你的应用程序增长更大时,它就越重要
(属性绑定)PROPERTY BINDINGS
Angular 使用属性绑定与组件树上的MODEL和DOM自动同步,要理解为什么这是很重要的,让我们来看看这个应用程序。
![](http://www.kittencup.com/images/2015-07-17-Angular 2的核心概念/e.png)
我们知道,这个应用程序将会有一个组件树。除了这棵树,它还将有一个模型。我们说这是简单的JavaScript对象,如下所示:
现在,想象一下一个事件改变model。我很喜欢它的talks,我给它9.9。
如果我必须找到所有可能有改变的地方并手动更新他们,那将是很繁琐且易出错,我想要应用程序自动来反映这一变化,这就是属性绑定。
在Angular虚拟机一轮结束,它会检查每个组件的组件树。更具体地说,它会检查每一个属性绑定(每一个方括号,每一对大括号),并将更新组件。它还将更新DOM来匹配组件树的状态。
ZONES
在Angular 1 你必须使用scope.$apply来告诉框架需要检查更新的内容,在Angular 2中你不必担心这个问题,Angular 2使用Zone.js知道当前检查是必须得,这意味着在使用第3方库集成时不需要在调用scope.$apply方法