angular指令,目的在于影响Dom布局,或者修改Dom属性。
Directive分类
Component
an extension of @Directive()
Demo
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'idata',
templateUrl: './user.component.html',
styleUrls: ['./user.component.scss']
})
export class UserComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
- @Component定义在class上
- templateUrl、template定义视图模板
@Component源码
export declare interface Component extends Directive {
changeDetection?: ChangeDetectionStrategy;
viewProviders?: Provider[];
moduleId?: string;
templateUrl?: string;
template?: string;
styleUrls?: string[];
styles?: string[];
animations?: any[];
encapsulation?: ViewEncapsulation;
interpolation?: [string, string];
entryComponents?: Array<Type<any> | any[]>;
preserveWhitespaces?: boolean;
}
从中我们得出如下:
- Component是一种特殊的指令
- Component 上述自有属性,都是可选
- 那么Directive的源码又是什么呢?
@Directive源码
export declare interface Directive {
selector?: string;
inputs?: string[];
outputs?: string[];
providers?: Provider[];
exportAs?: string;
queries?: {
[key: string]: any;
};
host?: {
[key: string]: string;
};
jit?: true;
}
属性指令
Attribute directives are used as attributes of elements
内置指令
- NgStyle
- NgClass
自定义指令
- step 1:
# 要求不能ng开头
ng generate directive highlight
- code如下:
# src/app/highlight.directive.ts
import { Directive } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor() { }
}
- step 2: 添加指令处理逻辑
import { Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef) {
# 修改元素背景
el.nativeElement.style.backgroundColor = 'yellow';
}
}
- step3: 模块中声明指令的存在
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HighlightDirective } from './highlight.directive';
@NgModule({
declarations: [
AppComponent,
HighlightDirective # 视图中声明指令的引用
],
imports: [
BrowserModule,
AppRoutingModule,
],
providers: [],
bootstrap: [AppComponent],
exports: []
})
export class AppModule { }
- step 4: 应用指令
<p appHighlight>Highlight me!</p>
结构指令
Structural directives are responsible for HTML layout
- 结构指令,影响当前元素以及后代元素
- 结构指令,大多以*开头
内置结构指令
- ngIf
# false,不渲染元素,而非渲染后隐藏
<div *ngIf="hero" class="name">{{hero.name}}</div>
- ngIf false为何不隐藏元素,而是删除元素? 这里应该是框架设计者针对利弊的取舍吧!如果元素仅仅隐藏,那么元素还占据原来的位置,那么对应的鼠标事件,有可能还是存在的,那么就会影响现有组件的功能,视图渲染数据。 具体的可以参考这边文章针对visible,opacity,hiden之间区别,写的挺好的!
- angular 编译ngIf为以下代码:
<ng-template [ngIf]="hero"> <div class="name">{{hero.name}}</div> </ng-template>
- ngFor
<div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
({{i}}) {{hero.name}}
</div>
- angular编译为以下代码 :
<ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById">
<div [class.odd]="odd">({{i}}) {{hero.name}}</div>
</ng-template>
- ngSwitch
<div [ngSwitch]="hero?.emotion">
<app-happy-hero *ngSwitchCase="'happy'" [hero]="hero"></app-happy-hero>
<app-sad-hero *ngSwitchCase="'sad'" [hero]="hero"></app-sad-hero>
<app-confused-hero *ngSwitchCase="'confused'" [hero]="hero"></app-confused-hero>
<app-unknown-hero *ngSwitchDefault [hero]="hero"></app-unknown-hero>
</div>
自定义结构指令
- step 1:
ng generate directive appUnless
- code 如下:
import { Directive } from '@angular/core'; @Directive({ selector: '[appUnless]' }) export class AppUnlessDirective { constructor() { } }
- step 2: 定义元素逻辑
import { Directive, TemplateRef, ViewContainerRef, Input } from '@angular/core';
@Directive({
selector: '[appUnless]'
})
export class AppUnlessDirective {
private hasView = false;
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) { }
@Input() set appUnless(condition: boolean) {
if (!condition && !this.hasView) {
this.viewContainer.createEmbeddedView(this.templateRef);
this.hasView = true;
} else if (condition && this.hasView) {
this.viewContainer.clear();
this.hasView = false;
}
}
}
- step 3: 声明指令
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HighlightDirective } from './highlight.directive';
import { AppUnlessDirective } from './app-unless.directive';
@NgModule({
declarations: [
AppComponent,
HighlightDirective,
AppUnlessDirective # 声明结构指令
],
imports: [
BrowserModule,
AppRoutingModule,
],
providers: [],
bootstrap: [AppComponent],
exports: []
})
export class AppModule { }
- step 4: 应用指令
<p *appUnless="condition" class="unless a">
(A) This paragraph is displayed because the condition is false.
</p>
#ts
public condition = false;
constructor(private domSanitizer: DomSanitizer){
interval(2000).subscribe(() => {
this.condition = !this.condition;
});
}