Angular学习笔记—架构简述
这个架构图展现了 Angular 应用中的 8 个主要构造块:
- 模块 (module)
- 组件 (component)
- 模板 (template)
- 元数据 (metadata)
- 数据绑定 (data binding)
- 指令 (directive)
- 管道
- 服务 (service)和依赖注入 (dependency injection)
图中的模板 (Templates)是由 Angular 扩展的 HTML 语法组成,组件 (Components)类用来管理这些模板,应用逻辑部分通过服务 (Services)来完成,然后在模块中打包服务与组件,最后通过引导根模块来启动应用。
模块 (module)
模块由一块代码组成,可用于执行一个简单的任务。
Angular 应用是由模块化的,它有自己的模块系统:NgModules。
每个 Angular 应该至少要有一个模块(根模块),一般可以命名为:AppModule。
Angular 模块是一个带有 @NgModule 装饰器的类,它接收一个用来描述模块属性的元数据对象。
@NgModule几个重要的属性如下:
imports:声明本模块引入的其它模块。
providers:声明本模块引入的服务类。如果在根模块中声明,则它们在应用中的任何部分都可被访问到。
declarations:声明本模块中拥有的视图类。Angular 有三种视图类:组件、指令和管道。
exports:声明( declaration )的子集,可用于其它模块中的组件模板 。
bootstrap 指定应用的主视图(称为根组件),它是所有其它视图的宿主。只有根模块才能设置 bootstrap 属性。
//app.module.ts import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [ BrowserModule ],
providers: [ Logger ],
declarations: [ AppComponent ],
exports: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
一个最简单的根模块:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [ BrowserModule ],
providers: [ Logger ],
declarations: [ AppComponent ],
exports: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
接下来我们通过引导根模块来启动应用,开发过程通常在 main.ts 文件中来引导 AppModule ,代码如下:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module'; platformBrowserDynamic().bootstrapModule(AppModule);
组件 (component)
组件是一个模板的控制类用于处理应用和逻辑页面的视图部分。
组件是构成 Angular 应用的基础和核心,可用于整个应用程序中。
组件知道如何渲染自己及配置依赖注入。
组件通过一些由属性和方法组成的 API 与视图交互。
创建 Angular 组件的方法有三步:
- 从 @angular/core 中引入 Component 修饰器
- 建立一个普通的类,并用 @Component 修饰它
- 在 @Component 中,设置 selector 自定义标签,以及 template 模板
模板 (template)
Angular模板的默认语言就是HTML。
我们可以通过使用模板来定义组件的视图来告诉 Angular 如何显示组件。以下是一个简单是实例:
<div>
网站地址 : {{site}}
</div>
在Angular中,默认使用的是双大括号作为插值语法,大括号中间的值通常是一个组件属性的变量名。
元数据 (metadata)
元数据告诉 Angular 如何处理一个类。
考虑以下情况我们有一个组件叫作 Component ,它是一个类,直到我们告诉 Angular 这是一个组件为止。
你可以把元数据附加到这个类上来告诉 Angular Component 是一个组件。
在 TypeScript 中,我们用 装饰器 (decorator) 来附加元数据。
实例
@Component({
selector : 'mylist',
template : '<h2>菜鸟教程</h2>'
directives : [ComponentDetails]
})
export class ListComponent{...}
@Component 装饰器能接受一个配置对象,并把紧随其后的类标记成了组件类。
Angular 会基于这些信息创建和展示组件及其视图。
@Component 中的配置项说明:
selector - 一个 css 选择器,它告诉 Angular 在 父级 HTML 中寻找一个 <mylist> 标签,然后创建该组件,并插入此标签中。
templateUrl - 组件 HTML 模板的地址。或者直接写html内容,用“`”括起来
directives - 一个数组,包含此模板需要依赖的组件或指令。
providers - 一个数组,包含组件所依赖的服务所需要的依赖注入提供者。
数据绑定 (data binding)
数据绑定为应用程序提供了一种简单而一致的方法来显示数据以及数据交互,它是管理应用程序里面数值的一种机制。
通过这种机制,可以从HTML里面取值和赋值,使得数据的读写,数据的持久化操作变得更加简单快捷。
如图所示,数据绑定的语法有四种形式。每种形式都有一个方向——从 DOM 来、到 DOM 去、双向,就像图中的箭头所示意的。
代码例子:
//插值表达式 在 HTML 标签中显示组件值。
<li>{{hero.name}}</li> //属性绑定 把父组件HeroListComponent
的selectedHero
的值传到子组件HeroDetailComponent
的hero
属性中。
<hero-detail [hero]="selectedHero"></hero-detail> //事件绑定 用户点击英雄的名字时调用组件的selectHero方法。
<li (click)="selectHero(hero)"></li> //双向绑定 数据属性值通过属性绑定从组件流到输入框。用户的修改通过事件绑定流回组件,把属性值设置为最新的值。
<input [(ngModel)]="hero.name">
可能大家对各种括号看的眼花了,总结一下:
- 双花括号是单向绑定,传递的是值。方向是
组件 -> 模板
。 - 方括号是单向绑定,传递的是属性。方向是
组件 -> 模板
。 - 圆括号是事件绑定,处理
点击等活动(action)
。方向是 模板-> 组件
。 - 方括号套圆括号是双向绑定,方向是
组件 <-> 模板
。
指令 (directive)
Angular模板是动态的 。当 Angular 渲染它们时,它会根据指令对 DOM 进行修改。
指令是一个带有"指令元数据"的类。在 TypeScript 中,要通过 @Directive 装饰器把元数据附加到类上。
在Angular中包含以下三种类型的指令:
- 属性指令:以元素的属性形式来使用的指令。
- 结构指令:用来改变DOM树的结构
- 组件:作为指令的一个重要子类,组件本质上可以看作是一个带有模板的指令。
<li *ngFor="let site of sites"></li>
<site-detail *ngIf="selectedSite"></site-detail>
*ngFor 告诉 Angular 为 sites 列表中的每个项生成一个 <li> 标签。
*ngIf 表示只有在选择的项存在时,才会包含 SiteDetail 组件。
管道
Angular 的管道可以让你在模板中声明显示值的转换逻辑。 带有 @Pipe
装饰器的类中会定义一个转换函数,用来把输入值转换成供视图显示用的输出值。
Angular 自带了很多管道,比如 date 管道和 currency 管道,完整的列表参见 Pipes API 列表。你也可以自己定义一些新管道。
要在 HTML 模板中指定值的转换方式,请使用 管道操作符 (|)。
{{interpolated_value | pipe_name}}
你可以把管道串联起来,把一个管道函数的输出送给另一个管道函数进行转换。 管道还能接收一些参数,来控制它该如何进行转换。比如,你可以把要使用的日期格式传给 date
管道:
<!-- Default format: output 'Jun 15, 2015'--> <p>Today is {{today | date}}</p> <!-- fullDate format: output 'Monday, June 15, 2015'--> <p>The date is {{today | date:'fullDate'}}</p> <!-- shortTime format: output '9:43 AM'--> <p>The time is {{today | date:'shortTime'}}</p>
服务 (service)
服务是一个广义的概念,它包括应用所需的任何值、函数或特性。狭义的服务是一个明确定义了用途的类。它应该做一些具体的事,并做好。
Angular 把组件和服务区分开,以提高模块性和复用性。
通过把组件中和视图有关的功能与其他类型的处理分离开,你可以让组件类更加精简、高效。 理想情况下,组件的工作只管用户体验,而不用顾及其它。 它应该提供用于数据绑定的属性和方法,以便作为视图(由模板渲染)和应用逻辑(通常包含一些模型的概念)的中介者。
组件不应该定义任何诸如从服务器获取数据、验证用户输入或直接往控制台中写日志等工作。 而要把这些任务委托给各种服务。通过把各种处理任务定义到可注入的服务类中,你可以让它可以被任何组件使用。 通过在不同的环境中注入同一种服务的不同提供商,你还可以让你的应用更具适应性。
Angular 不会强制遵循这些原则。它只会通过依赖注入让你能更容易地将应用逻辑分解为服务,并让这些服务可用于各个组件中。
依赖注入 (dependency injection)
依赖注入是提供类的新实例的一种方式,还负责处理类所需的全部依赖。大多数依赖都是服务。 Angular 使用依赖注入来提供新组件以及组件所需的服务。
比如我们要给某组件导入 HeroService 这个服务,看这段代码:
constructor(private service: HeroService) {
...
}
当 Angular 创建组件时,会首先为组件所需的服务找一个注入器( Injector ) 。
注入器是一个维护服务实例的容器,存放着以前创建的实例。
如果容器中还没有所请求的服务实例,注入器就会创建一个服务实例,并且添加到容器中,然后把这个服务返回给 Angular 。
当所有的服务都被解析完并返回时, Angular 会以这些服务为参数去调用组件的构造函数。 这就是依赖注入 。
我们必须先用注入器 injector 为 HeroService 注册一个提供商 provider。意思就是我们必须在 providers 写上才能用,看这段代码:
@Component({
selector: 'hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})
Angular学习笔记—架构简述的更多相关文章
- angular学习笔记(三十一)-$location(2)
之前已经介绍了$location服务的基本用法:angular学习笔记(三十一)-$location(1). 这篇是上一篇的进阶,介绍$location的配置,兼容各版本浏览器,等. *注意,这里介绍 ...
- angular学习笔记(三十一)-$location(1)
本篇介绍angular中的$location服务的基本用法,下一篇介绍它的复杂的用法. $location服务的主要作用是用于获取当前url以及改变当前的url,并且存入历史记录. 一. 获取url的 ...
- angular学习笔记(三十)-指令(10)-require和controller
本篇介绍指令的最后两个属性,require和controller 当一个指令需要和父元素指令进行通信的时候,它们就会用到这两个属性,什么意思还是要看栗子: html: <outer‐direct ...
- angular学习笔记(三十)-指令(7)-compile和link(2)
继续上一篇:angular学习笔记(三十)-指令(7)-compile和link(1) 上一篇讲了compile函数的基本概念,接下来详细讲解compile和link的执行顺序. 看一段三个指令嵌套的 ...
- angular学习笔记(三十)-指令(7)-compile和link(1)
这篇主要讲解指令中的compile,以及它和link的微妙的关系. link函数在之前已经讲过了,而compile函数,它和link函数是不能共存的,如果定义了compile属性又定义link属性,那 ...
- angular学习笔记(三十)-指令(6)-transclude()方法(又称linker()方法)-模拟ng-repeat指令
在angular学习笔记(三十)-指令(4)-transclude文章的末尾提到了,如果在指令中需要反复使用被嵌套的那一坨,需要使用transclude()方法. 在angular学习笔记(三十)-指 ...
- angular学习笔记(三十)-指令(5)-link
这篇主要介绍angular指令中的link属性: link:function(scope,iEle,iAttrs,ctrl,linker){ .... } link属性值为一个函数,这个函数有五个参数 ...
- angular学习笔记(三十)-指令(2)-restrice,replace,template
本篇主要讲解指令中的 restrict属性, replace属性, template属性 这三个属性 一. restrict: 字符串.定义指令在视图中的使用方式,一共有四种使用方式: 1. 元素: ...
- angular学习笔记(三十)-指令(1)-概述
之前在 angular学习笔记(十九)-指令修改dom 里面已经简单的提到了angular中的指令,现在来详细的介绍 '指令' 一.指令的创建: dirAppModule.directive('dir ...
随机推荐
- PHP学习笔记(7)验证码优化
php代码,主要把RGB改成随机生成,不是之前固定的七种颜色了: <?php // ob_clean(); header("content-type:image/png"); ...
- springmvc中配置servlet初始化类
<bean id="InitStart" lazy-init="false" init-method="InitSystem" cl ...
- Oracle 错误 maximum number of processes(150) exceeded 解决办法
网上很多同行应该都遇到过这个问题,百度一搜 千篇一律的处理办法,就是加大进程数. 但是我这边情况不一样,因为我的Oracle 11g是早上刚装的,跟本没人用,我用PLSQL链接照样说不能链接. 我就在 ...
- VM虚拟机不能上网的问题解决
VM虚拟机不能上网的问题解决 说在前面的话:很多网友看了我的文章后,虚拟机还是不能上网,就联系我帮忙,结果帮他们给弄好后,都说怪自己太粗心,没有仔细看文章.我不是怕网友麻烦我,我是真诚的希望各位要首先 ...
- linux2.4中netfilter_nat_alg机制分析--以FTP流程为例,分析NAT和ALG
以FTP流程为例,分析NAT和ALG 网络环境: ×5+6=1286) 创建×5+6=1286),更新skb的应用层信息(这里应用层信息还是×5+6=1286) 创建×5+6=1286) 创建×5+6 ...
- MapReduce实战(二)自定义类型排序
需求: 基于上一道题,我想将结果按照总流量的大小由大到小输出. 思考: 默认mapreduce是对key字符串按照字母进行排序的,而我们想任意排序,只需要把key设成一个类,再对该类写一个compar ...
- 拖拽 支持ie6
可随意拖拽方块至任一位置: 1.setCapture方法:多用于容器对象,效果是对指定的对象设置鼠标捕获.使在容器内的子对象的鼠标事件均由容器对象触发,因此,只能在容器对象的鼠标事件函数中进行处理.当 ...
- HBase之HFile解析
Sumary: Protobuf BinarySearch 本篇主要讲HFileV2的相关内容,包括HFile的构成.解析及怎么样从HFile中快速找到相关的KeyValue.基于Hbase 0.98 ...
- json DateTime转换
前台: function ChangeDateFormat(jsondate) { jsondate = jsondate.replace("/Date(", "&quo ...
- mui 单页面下拉刷新
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...