1 @Component({ 2 selector: 'app-heroes', 3 templateUrl: './heroes.component.html', 4 styleUrls: ['./heroes.component.css'] 5 })
在使用表单输入绑定数据以前,咱们须要引入表单模块FormsModule
包至咱们的Angular模块中。引入包的方法是,直接添加须要的包至NgModel
的imports
数组中。javascript
1 import { BrowserModule } from '@angular/platform-browser'; 2 import { NgModule } from '@angular/core'; 3 import { FormsModule } from '@angular/forms'; 4 5 import { AppComponent } from './app.component'; 6 import { HeroesComponent } from './heroes/heroes.component'; 7 8 9 @NgModule({ 10 declarations: [ 11 AppComponent, 12 HeroesComponent 13 ], 14 imports: [ 15 BrowserModule, 16 FormsModule 17 ], 18 providers: [], 19 bootstrap: [AppComponent] 20 }) 21 export class AppModule { }
表单中写法:css
1 <input [(ngModel)]="hero.name" placeholder="name">
1 const HEROES: Hero[] = [ 2 {id: 11, name: 'Mr.Nice'}, 3 {id: 12, name: 'Narco'}, 4 {id: 13, name: 'Bombasto'}, 5 {id: 14, name: 'Celeritas'}, 6 {id: 15, name: 'Magneta'}, 7 {id: 16, name: 'RubberMan'}, 8 {id: 17, name: 'Dynama'}, 9 {id: 18, name: 'Dr IQ'}, 10 {id: 19, name: 'Magma'}, 11 {id: 20, name: 'Tornado'} 12 ];
li
1 <li *ngFor="let hero of heroes"> 2 <span class="badge">{{hero.id}}</span> 3 {{hero.name}} 4 </li>
1 @Component({ 2 selector: 'my-app', 3 template: ``, 4 styles: [` 5 .selected { 6 background-color: #CFD8DC; 7 color:white; 8 } 9 .heroes { 10 margin: 0 0 2em 0; 11 list-style-type: none; 12 padding: 0; 13 width: 15em; 14 } 15 `] 16 }]
与Java/C++定义变量的类型写在前面不一样的时,TypeScript的定义方式为html
变量名:类型
java
1 selectedHero:Hero;
必须定义返回类型web
1 onSelect(hero: Hero): void { 2 this.selectedHero = hero; 3 }
直接使用某个可能为空的变量,会致使异常抛出,须要使用if
结构进行判断。angular中有一种名为结构指令(structural directives)
能够改变DOM的结构。这类的指令有ngIf
和ngFor
。用法以下:数据库
1 <div *ngIf="selectedHero"> 2 <h2>{{selectedHero.name}} details!</h2> 3 <div><label>id:</label>{{selectedHero.id}}</div> 4 <div><label>name:</label>{{selectedHero.name}}</div> 5 </div>
[class.className]=true/falsejson
key为样式的类名,value为true或者false.应用:已选择的项添加已选择
样式。未选择的项消除已选择
样式bootstrap
1 <li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero"> 2 <span class="badge">{{hero.id}}</span> 3 {{hero.name}} 4 </li>
1 import { Hero } from './hero';
使用@Injectable
修饰类api
import {Injectable} from '@angular/core'; import {HEROES} from "./mock-heroes"; import {Hero} from "./hero"; @Injectable() export class HeroServie { getHeroes(): Hero[] { return HEROES } }
如何在组件中使用这个服务?传统的方式会使用new
关键字去实例化。但官方不建议这么作,有如下几点理由:数组
当服务类的构造方法改变时,咱们必需要修改每一处使用到它的代码
若是须要缓存对象的状态,每次都new是作不到的。
在代码中写死new类来实例化,将没法替换其实现。好比,测试环境和生产环境的服务可能不一样,当要切换不一样版本是比较麻烦的。
官方推荐使用注入
来使用服务。为组件添加providers
元数据。
1 providers: [HeroServie],
组件的构造方法改成:
1 constructor(private heroService: HeroServie) { 2 this.heroes = heroService.getHeroes(); 3 }
ngOnInit
生命周期回调接口angular提供了一系统的接口监控组件的生命周期各个环节。
1 import { OnInit } from '@angular/core'; 2 3 export class AppComponent implements OnInit { 4 5 ngOnInit(): void { 6 7 // somthing to be done 8 9 } 10 11 }
Promise
解决回调的问题服务有时候是耗时的操做,若是直接调用可能会阻塞UI,使用Promise能够解决这个问题。
1 @Injectable() 2 export class HeroServie { 3 getHeroes(): Promise<Hero[]> { 4 return Promise.resolve(HEROES); 5 } 6 7 }
1 private getHeroes() : void { 2 this.heroService.getHeroes().then(heroes => this.heroes = heroes); 3 }
路由配置文件写法
import {Routes, RouterModule} from "@angular/router"; import {ModuleWithProviders} from "@angular/core"; import {HeroesComponent} from "./heroes.component"; const appRoutes: Routes = [{ path: 'heroes', component: HeroesComponent }]; export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
模板中使用
1 <a routerLink="/heroes">Heroes</a> 2 <router-outlet></router-outlet>
routerLink指令告知路由器点击跳转至哪一个地址,<router-outlet></router-outlet>
表示路由出口,即要把组件(routerLink指向的组件)
加载在哪一个位置.
1 @Component({ 2 selector: 'my-dashboard', 3 templateUrl: 'app/dashboard.component.html' 4 })
1 this.heroService.getHeroes().then(heroes=>this.heroes = heroes.slice(1, 5));
路由配置:id为参数
1 { 2 path: 'detail/:id', 3 component: HeroDetailComponent 4 }
获取参数:
1 export class HeroDetailComponent implements OnInit { 2 ngOnInit(): void { 3 this.route.params.forEach((params: Params)=> { 4 let id = +params['id']; //加号的做用是将字符串参数转化为数字 5 this.heroService.getHero(id).then(hero => this.hero = hero); 6 }); 7 } 8 9 constructor(private heroService: HeroServie, 10 private route: ActivatedRoute) { 11 12 } 13 14 @Input() 15 hero: Hero; 16 17 }
1 gotoDetail(hero: Hero): void { 2 let link = ['/detail', hero.id]; 3 this.router.navigator(link); 4 }
内存数据模拟数据库数据。
1 InMemoryWebApiModule.forRoot(InMemoryDataService),
service实现
1 import {InMemoryDbService} from "angular2-in-memory-web-api"; 2 3 export class InMemoryDataService implements InMemoryDbService { 4 createDb(): {} { 5 let heroes = [ 6 {id: 11, name: 'Mr. Nice'}, 7 {id: 12, name: 'Narco'}, 8 {id: 13, name: 'Bombasto'}, 9 {id: 14, name: 'Celeritas'}, 10 {id: 15, name: 'Magneta'}, 11 {id: 16, name: 'RubberMan'}, 12 {id: 17, name: 'Dynama'}, 13 {id: 18, name: 'Dr IQ'}, 14 {id: 19, name: 'Magma'}, 15 {id: 20, name: 'Tornado'} 16 ] 17 return heroes; 18 } 19 20 }
HTTP请求示例
1 getHeroes(): Promise<Hero[]> { 2 return this.http 3 .get(this.heroesUrl) 4 .toPromise() 5 .then(response => response.json().data as Hero[]) // 转换类型 6 .catch(this.handleError) 7 }
Angular的http.get
返回的是Observable
,Observables是一个强大的管理异步数据流的方式。
当咱们使用toPromise
方法将Observables转化为Promise后,操做就像操做普通的Promise同样。使用toPromise方法须要引入外部方法
1 import 'rxjs/add/operator/toPromise';
1 .catch(this.handleError);
1 private handleError(error: any): Promise<any> { 2 3 console.error('An error occurred', error); // for demo purposes only 4 5 return Promise.reject(error.message || error); 6 7 }
angular体系主要包括:模块Module,组件Component,模板Template,元数据Metadata,数据绑定Data Banding,服务Service,指令,依赖注入
模块是ES6标准之一,每一个模块目的性很是单一。在Angular中,通常模块输出的都是一个组件类,须要配合import
来加载模块。
有一类模块是Angular自己定义好的,即库模块,当加载angular2/core
模块时,能够调用一个核心类库。库模块入要有angular/core(核心类库)
,angular/http(网络请求相关)
,angular2/router(路由相关)
,angular2/common(表单、指令等)
1 总结 - Angular应用由模块组成 2 3 - 模块输出能够是:类、函数、值或其余模块
组件是为了控制显示把HTML模板及样式。通常,每一个组件都配有一个类,用来定义业务能力。经过类的属性和方法与视图进行交互。
模板是为了告知Angular如何去渲染组件。Angular模板有其特殊的语法。
元数据是告知Angular如何处理一个类。一个类若是没有元数据的声明,就是一个没法单独运行的普通的类。可使用注解
来定义类的元数据。如@Component
,注解中能够带上一些参数:
1 - selector - CSS选择器 2 3 - templateUrl - 的模板地址 4 5 - directives - 指令或组件数组 6 7 - providers - 注册的Service服务数组,从而在组件类构造函数中可以正确的实例化这些服务
除了@Component
外,还有Injectable
,@Input
,@Output
,@RouterConfig
元数据。
数据绑定是一种协调组件与模板之间的通讯机制,经过HTML元素来描述采用哪一种数据绑定形式。数据绑定包括属性绑定[hero]
、事件绑定(click)
、双向绑定[(ngModel)]="hero.name"
指令。一个指令是由元数据和一个类组成,使用元数据注解@Directive
修饰就是一个指令。指令和组件的功能相似,他们的区别是指令侧重对HTML元素功能的扩展。而组件是一个具体一的业务。指令分为结构性指令如*ngFor
,*ngIf
等和属性指令,如[(ngModel)]
服务。模块中须要使用到的值、函数均可以是服务Service。服务一般 是一个目的性很是明确的类。如日志Service,数据Service,应用程序配置信息,工资计算器等 。
组件是是服务的最大消费者,组件都是靠服务来处理大部分事务,组件不会直接从服务器获取数据、不验证用户输入,都是委派验服务来完成。通常咱们遵循的原则是:把应用程序逻辑转化成服务 ,并经过依赖注入提供组件来消费服务。
依赖注入。依赖注入是一种对类实例的新方法。咱们能够在引导应用程序启动时实例一个服务如
1 bootstrap(AppComponent, [BackendService, HeroService, Logger]);
或者在组件级别里注册服务
1 @Component({ 2 providers: [HeroService] 3 }) 4 export class HeroesComponent { ... }
@Component({
selector: 'my-app',
template: `<h1>{{title}}</h1> <h2>{{hero.name}} details!</h2>
<div><label>id:</label>{{hero.id}}</div> <div><label>name:</label>{{hero.name}}</div>` })
在使用表单输入绑定数据以前,咱们须要引入表单模块FormsModule
包至咱们的Angular模块中。引入包的方法是,直接添加须要的包至NgModel
的imports
数组中。
import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {AppComponent} from './app.component';
import {FormsModule} from "@angular/forms";
@NgModule({
imports: [
BrowserModule,
FormsModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {
}
表单中写法:
<input [(ngModel)]="hero.name" placeholder="name">
const HEROES: Hero[] = [
{id: 11, name: 'Mr.Nice'},
{id: 12, name: 'Narco'},
{id: 13, name: 'Bombasto'},
{id: 14, name: 'Celeritas'},
{id: 15, name: 'Magneta'},
{id: 16, name: 'RubberMan'},
{id: 17, name: 'Dynama'},
{id: 18, name: 'Dr IQ'},
{id: 19, name: 'Magma'},
{id: 20, name: 'Tornado'}
];
li
<li *ngFor="let hero of heroes">
<span class="badge">{{hero.id}}</span>
{{hero.name}}
</li>
@Component({ selector: 'my-app', template: ``, styles: [` .selected {
background-color: #CFD8DC;
color:white;
}
.heroes { margin: 0 0 2em 0; list-style-type: none; padding: 0; width: 15em; }
`]
}]
与Java/C++定义变量的类型写在前面不一样的时,TypeScript的定义方式为
变量名:类型
selectedHero:Hero;
必须定义返回类型
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
直接使用某个可能为空的变量,会致使异常抛出,须要使用if
结构进行判断。angular中有一种名为结构指令(structural directives)
能够改变DOM的结构。这类的指令有ngIf
和ngFor
。用法以下:
<div *ngIf="selectedHero">
<h2>{{selectedHero.name}} details!</h2>
<div><label>id:</label>{{selectedHero.id}}</div>
<div><label>name:</label>{{selectedHero.name}}</div>
</div>
[class.className]=true/false
key为样式的类名,value为true或者false.应用:已选择的项添加已选择
样式。未选择的项消除已选择
样式。
<li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
<span class="badge">{{hero.id}}</span>
{{hero.name}}
</li>
import { Hero } from './hero';
使用@Injectable
修饰类
import {Injectable} from '@angular/core';
import {HEROES} from "./mock-heroes";
import {Hero} from "./hero";
@Injectable()
export class HeroServie {
getHeroes(): Hero[] {
return HEROES
}
}
如何在组件中使用这个服务?传统的方式会使用new
关键字去实例化。但官方不建议这么作,有如下几点理由:
当服务类的构造方法改变时,咱们必需要修改每一处使用到它的代码
若是须要缓存对象的状态,每次都new是作不到的。
在代码中写死new类来实例化,将没法替换其实现。好比,测试环境和生产环境的服务可能不一样,当要切换不一样版本是比较麻烦的。
官方推荐使用注入
来使用服务。为组件添加providers
元数据。
providers: [HeroServie],
组件的构造方法改成:
constructor(private heroService: HeroServie) {
this.heroes = heroService.getHeroes();
}
ngOnInit
生命周期回调接口angular提供了一系统的接口监控组件的生命周期各个环节。
import { OnInit } from '@angular/core';
export class AppComponent implements OnInit {
ngOnInit(): void {
// somthing to be done
}
}
Promise
解决回调的问题服务有时候是耗时的操做,若是直接调用可能会阻塞UI,使用Promise能够解决这个问题。
@Injectable()
export class HeroServie {
getHeroes(): Promise<Hero[]> {
return Promise.resolve(HEROES);
}
}
private getHeroes() : void {
this.heroService.getHeroes().then(heroes => this.heroes = heroes);
}
路由配置文件写法
import {Routes, RouterModule} from "@angular/router";
import {ModuleWithProviders} from "@angular/core";
import {HeroesComponent} from "./heroes.component";
const appRoutes: Routes = [{
path: 'heroes',
component: HeroesComponent
}];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
模板中使用
<a routerLink="/heroes">Heroes</a>
<router-outlet></router-outlet>
routerLink指令告知路由器点击跳转至哪一个地址,<router-outlet></router-outlet>
表示路由出口,即要把组件(routerLink指向的组件)
加载在哪一个位置.
@Component({
selector: 'my-dashboard',
templateUrl: 'app/dashboard.component.html'
})
this.heroService.getHeroes().then(heroes=>this.heroes = heroes.slice(1, 5));
路由配置:id为参数
{
path: 'detail/:id',
component: HeroDetailComponent
}
获取参数:
export class HeroDetailComponent implements OnInit {
ngOnInit(): void {
this.route.params.forEach((params: Params)=> {
let id = +params['id']; //加号的做用是将字符串参数转化为数字
this.heroService.getHero(id).then(hero => this.hero = hero);
});
}
constructor(private heroService: HeroServie,
private route: ActivatedRoute) {
}
@Input()
hero: Hero;
}
gotoDetail(hero: Hero): void {
let link = ['/detail', hero.id];
this.router.navigator(link);
}
内存数据模拟数据库数据。
InMemoryWebApiModule.forRoot(InMemoryDataService),
service实现
import {InMemoryDbService} from "angular2-in-memory-web-api";
export class InMemoryDataService implements InMemoryDbService {
createDb(): {} {
let heroes = [
{id: 11, name: 'Mr. Nice'},
{id: 12, name: 'Narco'},
{id: 13, name: 'Bombasto'},
{id: 14, name: 'Celeritas'},
{id: 15, name: 'Magneta'},
{id: 16, name: 'RubberMan'},
{id: 17, name: 'Dynama'},
{id: 18, name: 'Dr IQ'},
{id: 19, name: 'Magma'},
{id: 20, name: 'Tornado'}
]
return heroes;
}
}
HTTP请求示例
getHeroes(): Promise<Hero[]> {
return this.http
.get(this.heroesUrl)
.toPromise()
.then(response => response.json().data as Hero[]) // 转换类型
.catch(this.handleError)
}
Angular的http.get
返回的是Observable
,Observables是一个强大的管理异步数据流的方式。
当咱们使用toPromise
方法将Observables转化为Promise后,操做就像操做普通的Promise同样。使用toPromise方法须要引入外部方法。
import 'rxjs/add/operator/toPromise';
.catch(this.handleError);
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
}
angular体系主要包括:模块Module,组件Component,模板Template,元数据Metadata,数据绑定Data Banding,服务Service,指令,依赖注入
模块是ES6标准之一,每一个模块目的性很是单一。在Angular中,通常模块输出的都是一个组件类,须要配合import
来加载模块。
有一类模块是Angular自己定义好的,即库模块,当加载angular2/core
模块时,能够调用一个核心类库。库模块入要有angular/core(核心类库)
,angular/http(网络请求相关)
,angular2/router(路由相关)
,angular2/common(表单、指令等)
- Angular应用由模块组成
- 模块输出能够是:类、函数、值或其余模块
组件是为了控制显示把HTML模板及样式。通常,每一个组件都配有一个类,用来定义业务能力。经过类的属性和方法与视图进行交互。
模板是为了告知Angular如何去渲染组件。Angular模板有其特殊的语法。
元数据是告知Angular如何处理一个类。一个类若是没有元数据的声明,就是一个没法单独运行的普通的类。可使用注解
来定义类的元数据。如@Component
,注解中能够带上一些参数:
- selector - CSS选择器
- templateUrl - 的模板地址
- directives - 指令或组件数组
- providers - 注册的Service服务数组,从而在组件类构造函数中可以正确的实例化这些服务
除了@Component
外,还有Injectable
,@Input
,@Output
,@RouterConfig
元数据。
数据绑定是一种协调组件与模板之间的通讯机制,经过HTML元素来描述采用哪一种数据绑定形式。数据绑定包括属性绑定[hero]
、事件绑定(click)
、双向绑定[(ngModel)]="hero.name"
指令。一个指令是由元数据和一个类组成,使用元数据注解@Directive
修饰就是一个指令。指令和组件的功能相似,他们的区别是指令侧重对HTML元素功能的扩展。而组件是一个具体一的业务。指令分为结构性指令如*ngFor
,*ngIf
等和属性指令,如[(ngModel)]
服务。模块中须要使用到的值、函数均可以是服务Service。服务一般 是一个目的性很是明确的类。如日志Service,数据Service,应用程序配置信息,工资计算器等 。
组件是是服务的最大消费者,组件都是靠服务来处理大部分事务,组件不会直接从服务器获取数据、不验证用户输入,都是委派验服务来完成。通常咱们遵循的原则是:把应用程序逻辑转化成服务 ,并经过依赖注入提供组件来消费服务。
依赖注入。依赖注入是一种对类实例的新方法。咱们能够在引导应用程序启动时实例一个服务如
bootstrap(AppComponent, [BackendService, HeroService, Logger]);
或者在组件级别里注册服务
@Component({
providers: [HeroService]
})
export class HeroesComponent { ... }