1.响应用户时间 使用装饰器添加两个事件处理器,它们会在鼠标进入或离开时进行响应。
eg: @('mouseenter') onMouseEnter() {
this.highlight('yellow');}
@('mouseleave')onMouseLeave(){
this.highlight(null);}
privatehighlight(color:string){
this.el.nativeElement.style.backgroundColor=color;}
2、使用数据绑定向指令传递值
@Input() highlightColor:string
注意看@装饰器。它往类上添加了一些元数据,从而让该指令的highlightColor能用于绑定。
它之所以称为输入属性,是因为数据流是从绑定表达式流向指令内部的。 如果没有这个元数据,Angular就会拒绝绑定
@装饰器把属性设置成了公共属性。
3
生命周期的顺序
当Angular使用构造函数新建一个组件或指令后,就会按下面的顺序在特定时刻调用这些生命周期钩子方法:
钩子 | 目的和时机 |
ngOnChanges() | 当Angular(重新)设置数据绑定输入属性时响应。 该方法接受当前和上一属性值的 当被绑定的输入属性的值发生变化时调用,首次调用一定会发生在ngOnInit()之前。 |
ngOnInit() | 在Angular第一次显示数据绑定和设置指令/组件的输入属性之后,初始化指令/组件。 在第一轮ngOnChanges()完成之后调用,只调用一次。 |
ngDoCheck() | 检测,并在发生Angular无法或不愿意自己检测的变化时作出反应。 在每个Angular变更检测周期中调用,ngOnChanges()和ngOnInit()之后。 |
ngAfterContentInit() | 当把内容投影进组件之后调用。 第一次ngDoCheck()之后调用,只调用一次。 只适用于组件。 |
ngAfterContentChecked() | 每次完成被投影组件内容的变更检测之后调用。 ngAfterContentInit()和每次ngDoCheck()之后调用 只适合组件。 |
ngAfterViewInit() | 初始化完组件视图及其子视图之后调用。 第一次ngAfterContentChecked()之后调用,只调用一次。 只适合组件。 |
ngAfterViewChecked() | 每次做完组件视图和子视图的变更检测之后调用。 ngAfterViewInit()和每次ngAfterContentChecked()之后调用。 只适合组件。 |
ngOnDestroy | 当Angular每次销毁指令/组件之前调用并清扫。 在这儿反订阅可观察对象和分离事件处理器,以防内存泄漏。 在Angular销毁指令/组件之前调用。 |
4.写服务的注意事项。
a.创建。hero.service.ts的文件,
b,将要引入的data(数据---静态数据)创建一个单独的ts。在hero.service.ts 里用import引用
c,hero.service.ts里视情况使用promise
eg:
import {Injectable} from '@angular/core'
import {Hero} from '../class/hero'
import {HEROES} from '../staticdata/initdata'
@Injectable()
export class HeroService{
getHeroes(): Promise<Hero[]> {
return Promise.resolve(HEROES)
}
}
d.在调用的组件里面实例化service类。注意不要这样实例化。 heroService = new HeroService(); // don't do this,不妥;即做这两份操作
1, constructor(private heroService: HeroService) { }
2, 在@组件的元数据底部添加providers数组属性如下: providers: [HeroService]
5、创建最外端的app壳子时需要selector设置的字符串标签在index.html 能找到。
eg:app 组件的代码
@Component({
selector: 'app-root',
templateUrl: './appContainer.component.html'
})
index.html代码
<body>
<app-root></app-root>
</body>
6、angular4的路由创建。
a、index.html页面必须有<base href= "/">
b、在app.module.ts的imports属性里面加入RouterModule.forRoot(),里面加入数组
eg:
imports: [
,
,
.forRoot([
{
path: 'heroes',
component: HeroesComponent
}
])
],
c, 路由器就把激活的组件显示在<router-outlet>里面。并且通过a标签进行导航跳转<a routerLink="/heroes">Heroes</a>
d、路由的重定向
{
path:' ',
redirectTo:'/dashboard',
pathMatch:'full'
}
e、带参数的路由配置,配置的结果是
配置: { path: 'detail/:id', component: HeroDetailComponent},
结果:/detail/11
注意:组件中数据的传输
1、从父组件的属性绑定中接收英雄数据
2、新的HeroDetailComponent应该从服务的可观察对象params中取得id参数, 并通过HeroService服务获取具有这个指定id的英雄数据。
f、路由如果是要进行迭代的话[routerLink]="['detail',hero.id]"
eg: <a *ngFor="let hero of heroes" [routerLink]="['/detail', hero.id]" class="col-1-4">
g.对于路由的配置可以先将其填充到一个数组里、再将定义的数组填充到router的方法里
添加.forRoot(routes)到imports。
如果有守卫服务,把它们添加到本模块的providers中(本例子中没有守卫服务)。
eg:
const routes: = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'detail/:id', component: HeroDetailComponent },
{ path: 'heroes', component: HeroesComponent }
];
@({
imports: [ .forRoot(routes) ],
exports: [ ]
})
7、编码式路由跳转<这三步在进行函数化路由跳转时,在该跳转组件上必须存在>
1、从angular路由器库导入Router
import {Router} from '@angular/router'
2、在构造函数中注入(与HeroService一起)
constructor(
private router: ,
private heroService: HeroService) { }
3、 实现gotoDetail(),调用路由器的navigate()方法
gotoDetail(): void { this.router.navigate(['/detail',this.selectedHero.id]);}
传数值键参数
this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]);
8、路由中子组件获取参数。
a: 1.在查询参数中传递参数 /product?id=1&name=2 this.productId=this.routerInfo.snapahot.queryParams["id"]
步骤分解。| 注入ActivatedRoute .eg: import {ActivatedRoute, Router} from "@angular/router"
||在构造函数中构造。eg: constructor(private routerIonfo:ActivatedRoute) { }
||||在本组件创建一个变量 eg: private productId:number
|V在本组件中加方法。 eg: ngOnInit(){
this.productId=this.routerInfo.snapshot.queryParams["id"]
}
注意:这种方法只能初始化第一次的时候获取一次数据不能,随数据变化而变化。如需要变化可以采用订阅发布者模式。
b.在路由路径中传递数据
//路由配置{path:'/product/:id'}
//路由显示方式Restful=>/product/1
/** 获取参数 *
/=>ActivatedRoute.params[id]
export class HomeComponent implements OnInit {
private homeId:number;
constructor(private routerIonfo:ActivatedRoute) { }
ngOnInit() {
this.homeId=this.routerIonfo.snapshot.params["id"];
}
}
优化版就是加订阅
this.routerIonfo.params.subscribe((params:Params)=>this.homeId=params["id"]);
注意: a、只有当你确定你的页面不会从自身路由到自身,或者只有一只方式路由到此页面的话就可以使用参数快照方式,不确定的话最好使用参数订阅的方式。
b、防止页面跳转没定义的路由导致程序奔溃需要配置通配符路由:
eg: { path: '**', component: PageNotFoundComponent }
c、 { path: '', redirectTo: '/heroes', pathMatch: 'full' } 在本应用中,路由器应该只有在完整的URL等于''时才选择HeroListComponent组件,因此我们要把pathMatch设置为'full'。
d、 pathMatch的另一个可能的值是'prefix',它会告诉路由器:当剩下的URL以这个跳转路由中的prefix值开头时,就会匹配上这个跳转路由。
8、路由模块
路由模块有一系列特性:
- 把路由这个关注点从其它应用类关注点中分离出去
- 测试特性模块时,可以替换或移除路由模块
- 为路由服务提供商(包括守卫和解析器等)提供一个共同的地方
- 不要
imports: [
,
,
HeroesModule,
AppRoutingModule],
AppRoutingModule
是最后一个。最重要的是,它位于HeroesModule之后。路由配置的顺序很重要。 路由器会接受第一个匹配上导航所要求的路径的那个路由。
当所有路由都在同一个AppRoutingModule时,我们要把默认路由和放在最后(这里是在/heroes路由后面), 这样路由器才有机会匹配到/heroes路由,否则它就会先遇到并匹配上该通配符路由,并导航到“页面未找到”路由。
一些注意
问题1.
解决方法:
引入下面代码:
import 'rxjs/add/operator/switchMap';
二、
<li *ngFor="let heroa of heroes" (click)="onSelect(heroa)">
<span>{
{heroa.id}}</span><h1>{ {heroa.name}}</h1><button class="delete"(click)="delete(hero);$event.stopPropagation()">X</button>
</li>
注:$event.stopPropagation()阻止事件冒泡,阻止它向上触发li的事件