Angular 学习日记 - 2 - 指令(Directive)

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;
}
@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 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为何不隐藏元素,而是删除元素? 这里应该是框架设计者针对利弊的取舍吧!如果元素仅仅隐藏,那么元素还占据原来的位置,那么对应的鼠标事件,有可能还是存在的,那么就会影响现有组件的功能,视图渲染数据。 

  • 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;
  });
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值