Angular directive 之自定义指令 | 更文挑战第7天

1,153 阅读2分钟

这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

如何自定义指令

写一个通过点击给img添加不同class的指令,div 的html如下

html

<img src='' alt='xxx' imageEnlarged class='image-default'>

法1: host里操作class


import { Directive, ElementRef, Renderer2 } from '@angular/core';

@Directive({
    selector: '[imageEnlarged]',
    host : {
        '[class.image-enlarged]' : 'toggle', //  toggle为true的时候添加 class image-enlarged
        '[class.image-default]' : '!toggle', // toggle为false的时候添加 class image-default
        '(click)' : 'clickImg()'
    }
})

export class ImageDirective {
    toggle: boolean = false;
    
    clickImg(){
      this.toggle = !this.toggle;
    }
}

法2: 操作dom元素添加class

import { Directive, ElementRef, Renderer2 } from '@angular/core';

@Directive({
  selector: '[imageEnlarged]',
  host : {
    '(click)' : 'clickImg()'
    }
})
export class ImageDirective {
    toggle : boolean = false;
    classArr = ['image-enlarged', "image-default"];
    
    constructor(private el: ElementRef, private renderer: Renderer2) {}
    
    clickImg(){
        this.toggle = !this.toggle;
        this.toggle 
            ? this.toggleClass(this.classArr[0], this.classArr[1])
            : this.toggleClass(this.classArr[1], this.classArr[0])
        }
    }
    
    toggleClass(increase, decrease){
        this.renderer.addClass(this.el.nativeElement, increase);
        this.renderer.removeClass(this.el.nativeElement, decrease);
    }   
}

自定义指令如何传递参数

用法和组件相同,使用prop传参, 使用@input接收

html

<div myDirective [disabled]="true"></div>

directive

@Directive({
  selector: '[myDirective]',
})
export class BtnToggleStatusDirective {
  @Input() disabled: boolean;
}

如何根据条件决定是否添加指令

有个指令,我想它有时候被添加上,有时候去除,可以传进去一个布尔值来实现吗?

不可以。没办法直接使用条件判断是否添加指令,不过可以分成两部分,一个添加了指令的区域,一个未添加的,再通过判断显示哪个。

未避免代码冗余将公用的部分抽取出来:

<ng-template #shared>
  <div>这是一个共享的内容</div>
</ng-template>

需要添加指令

<div *ngIf="show" yourDirective>
    <ng-container *ngTemplateOutlet="shared"></ng-container>
</div>

不需要添加指令

<div *ngIf="!show">
    <ng-container *ngTemplateOutlet="shared"></ng-container>
</div>

彩蛋

一个文件中同一段html被多次用到怎么抽离

可以抽离成一个组件,也可以使用ngTemplateOutlet来实现共享

比如说有一段代码

<div> 
   第一区域
   <p>共享的部分</p>
</div>

<div> 
   第二区域
   <p>共享的部分</p>
</div>

如何将共享的部分抽离出来呢?

<div>
    第一区域
    <ng-container *ngTemplateOutlet="shared"></ng-container>
</div>

<div>
    第二区域
    <ng-container *ngTemplateOutlet="shared"></ng-container>
</div>

<ng-template #shared>
  <p>共享的部分</p>
</ng-template>

ngTemplateOutlet接收的是一个模板名称,即#shared,可以自定义。如果想传递参数请查看该系列文章的ngTemplateOutlet介绍。

更多用法更新于 github