Angular2 @Component
Directive/指令
通过指令这一标记,给dom添加特定的自定义功能,如样式变化、结构调整、事件暴露等
使用方法
import {Directive} from '@angular/core';
@Directive({
selector: 'my-directive',// 选择器名.class/[attr]/div
providers: [],// 组件及子组件可使用的provider
inputs: ['inputColor'],// 输入到指令中的属性名
outputs: ['onRemove'],// 输出到指令外的事件名
exportAs: '',// 导出名
host: {// 事件代理,相当于在元素上添加上这种字符串
'(mouseover)': 'toLower()'
},
queries: []// 能被注入到组建中的query
})
export class MyDirective { }
属性型指令
改变被选择的元素的属性
Example:
<!-- ng2自带指令 -->
<!-- NgStyle -->
<p [style.background]="'blue'">I am green with envy!</p>
<!-- NgClass -->
<div [ngClass]="setClasses()">This div is saveable and special</div>
/*
* 自定义指令
* 给class包含dark-shadow的元素添加黑暗阴影
*/
import { Directive, ElementRef, Renderer } from '@angular/core';
@Directive({
selector: '.dark-shadow'
})
export class DarkShadowDirective {
constructor(el: ElementRef, renderer: Renderer) {
renderer.setElementStyle(el.nativeElement, 'text-shadow',
'0px 0px 4px black');
}
}
结构型指令
改变被选择的元素的结构
Example:
<!-- ng2自带指令 -->
<!-- NgIf -->
<div *ngIf="currentHero">Hello, {{currentHero.firstName}}</div>
<!-- NgFor -->
<div *ngFor="let hero of heroes">{{hero.fullName}}</div>
/*
* 自定义指令
* 将元素双倍展示
*/
import { Directive, Input } from '@angular/core';
import { TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[double]'
})
export class DoubleDirective {
constructor(private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) {
this.viewContainer.createEmbeddedView(this.templateRef);
this.viewContainer.createEmbeddedView(this.templateRef);
}
}
@Directive参数详解
// .className/[attrName]/tagName/混合写法
@Directive({
selector: '[blueBg]:not(p)'
})
选择器:标签名、类名、属性名、:not()
// 写法1.作为@Directive的元数据写入
@Directive({
selector: 'p'
inputs: ['customColor']
})
// 写法2.使用@Input装饰器写入(推荐)
@Directive({
selector: 'p'
})
export class ColorComponent {
@Input() customColor: string;
}
声明一个输入属性,以便我们可以通过属性绑定更新它
// 写法1.作为@Directive的元数据写入
@Directive({
selector: 'p'
outputs: ['onTalk']
})
// 写法2.使用@Output装饰器写入(推荐)
@Directive({
selector: 'p'
})
export class TalkComponent {
@Output() onSay: EventEmitter<any>;
}
声明一个输出属性,以便我们可以通过事件绑定进行订阅
@Directive({
selector: 'div'
providers: [CalcService]
})
指令及子指令可使用的provider(service)
@Directive({
selector: 'div'
exportAs: 'myDiv'
})
指令在模板中的替代名称
其他
- host:事件代理,使用后将在元素上添加对应属性
-
queries:能被注入到组建中的query
// queries参数
@Component({
selector: 'my-app',
queries: {
count: new ViewChild(CountComponent)
}
})
// host参数
@Directive({
selector: 'button[counting]',
host: {
'(click)': 'onClick($event.target)'
}
})
Component/组件
拥有模板、样式的指令
使用方法
import {Component} from '@angular/core';
@Component({
/* 和directive相同的属性 */
selector: 'my-component',
providers: [],
inputs: ['inputColor'],
outputs: ['onRemove'],
exportAs: '',
host: {
'(mouseover)': 'toLower()'
},
queries: [],
/* 不同于directive的属性 */
styleUrls: [],// 样式文件路径数组
styles: ['p {color:white;}'],
template: '<p>Hello World</p>',
templateUrl: '',// 模版文件路径
moduleId: '',// 组件在ES/CommonJS中的moduleId
animations: [],// 定义动画列表
changeDetection: ChangeDetectionStrategy.default,// 变化检测策略
encapsulation: ViewEncapsulation.Native,// 组件样式封装策略,Native/Emulated/None
entryComponents: [],// 会被动态添加的组件
interpolation: ['{{', '}}'],// 插值表达式符号替换
viewProviders: ''// 组件及子视图组件可使用的provider
})
export class MyComponent { }
ngContent
嵌入内容
- 将内容嵌入到组件模板中
-
类似于Angular 1中的transclude
-
可以使用select属性选择嵌入的元素
@Component({
selector: 'my-component',
template: `
<div>
<ng-content select="header"></ng-content>
<div style="border: 2px solid purple;">
<ng-content select="p"></ng-content>
</div>
</div>
`
})
class MyComponentElementComponent {}
组件的生命周期
监听组件各阶段事件
基本构建顺序
构建view元素
(即模板template中的元素)
构建content元素
(对应于ng1中的transclude)
初始化数据
勾子
class ParentElementComponent {
constructor() {}
// 当被绑定的输入属性(@Input)的值发生变化时调用
ngOnChanges(changes: any) {}
// 初始化指令/组件,仅一次
ngOnInit() {}
// 在每个Angular变更检测周期中调用
ngDoCheck() {}
// 当把内容投影进组件之后调用,仅一次
ngAfterContentInit() {}
// 检测内容投影的变化后调用
ngAfterContentChecked() {}
// 初始化完组件视图及其子视图之后调用,仅一次
ngAfterViewInit() {}
// 检测视图及其子视图的变化后调用
ngAfterViewChecked() {}
// 销毁时调用
ngOnDestroy() {}
}
构建顺序
[parent]
ngOnInit
ngDoCheck
ngAfterContentInit
ngAfterContentChecked
ngAfterViewInit
ngAfterViewChecked
[content]
ngOnInit
ngDoCheck
ngAfterContentInit
ngAfterContentChecked
ngAfterViewInit
ngAfterViewChecked
[child]
ngOnInit
ngDoCheck
ngAfterContentInit
ngAfterContentChecked
ngAfterViewInit
ngAfterViewChecked
组件样式
给组件设置独特的样式
设置组件样式
@Component({
selector: 'hero-app',
template: `
<h1>Tour of Heroes</h1>
<hero-app-main [hero]=hero></hero-app-main>
<style>
span { border: 1px solid black;}
</style>`,
styles: ['h1 { font-weight: normal; }'],
styleUrls: ['app/style.css']
})
- 内联在模板的 HTML 中
-
设置styles或styleUrls元数据
-
通过 CSS 文件导入
特殊选择器
- :host宿主元素选择器
- 直接作用于宿主元素
-
:host-context 宿主上下文
-
当宿主元素的上下文附和条件时,样式生效
-
-
/deep/ 深作用

宿主
视图封装模式
-
Emulated(默认)
- 通过预处理(并改名)CSS 代码来模拟 Shadow DOM 的行为
- 样式只进不出,不会影响内容投影、子组件
-
Native
-
使用浏览器原生的 Shadow DOM 实现
-
样式不进不出、会影响内容投影、子组件
-
-
None
-
不使用视图封装
-
样式能进能出
-
@Component({
selector: 'parent-element',
// 设置封装模式
encapsulation: ViewEncapsulation.Emulated
})
组件动画
赋予组件动画效果
状态
// 添加inactive状态
state('inactive', style({
backgroundColor: '#eee',
color: 'black'
}))
// 添加active状态
state('active', style({
backgroundColor: 'black',
color: 'white'
}))
- *表示任意动画状态
-
void表示元素未在视图的状态
内置状态
转场
// 从状态inactive到active时的转场
transition('inactive => active', animate('100ms ease-in')),
// 从状态active到inactive时的转场
transition('active => inactive', animate('100ms ease-out'))
- :enter表示进场
-
:leave表示出场
内置转场
添加动画
import {Component, style, state, trigger, animate, transition} from '@angular/core';
@Component({
selector: 'my-app',
animations: [
trigger('heroState', [
state('inactive', style({
backgroundColor: '#eee',
color: 'black'
})),
state('active', style({
backgroundColor: 'black',
color: 'white'
})),
transition('inactive => active', animate('100ms ease-in'))
],
template: `<h1 [@heroState]="state">Hello World</h1>`
})
组件通讯
组件之间传递状态、消息
@input/@output
- 通过输入型绑定,把数据从父组件传到子组件
- 通过输出型绑定,使父组件监听子组件事件
ngOnChanges
- 当输入型数据改变时,会调用生命周期中的ngOnChanges方法
- 此方法返回所有改变的数据值
本地变量与ViewChild
- 本地变量:在模板中访问
- ViewChild:在代码中访问
Service
- 创建一个单例service
- 父组件和子组件共享同一个service
- 通过监听service的变化来实现组件之间的通讯
The End-Q&A
- Directive
- 属性型指令
- 结构型指令
- 参数详解
- Component
- ngContent
- 生命周期
- 组件样式
- 组件动画
- 组件通讯
angular2-component
By leegend
angular2-component
- 304