Angular @Input()根据传入值自适应显示

在使用那NZ-ZORRO的时候发现很多组件的传入值既可以是sting类型,也可以是TemplateRef,比较灵活。我也试着实现这样的组件,开始使用ngTemplateOutlet来做的,发现只支持tempalte,传入string就报错了。后来看了ng-zorro的源码发现其实他们是根据类型判断走不同的ng-container来实现的。我以为这里用高级用法呢,有些失望。我也安ng-zorro的思路实现一下,逻辑比较简单,判断没那么多。

mport { Component, OnInit, ViewChild, TemplateRef,  Input } from '@angular/core';


@Component({
  selector: 'app-log-modal',
  template: `
    <ng-container [ngSwitch]="true">
      <ng-container *ngSwitchCase="isTemplateRef(logContent)">
        <pre><ng-container [ngTemplateOutlet]="logContent"></ng-container></pre>
      </ng-container>
      <ng-container *ngSwitchCase="isString(logContent)">
        <pre [innerHTML]="logContent"></pre>
      </ng-container>
      <ng-container *ngSwitchDefault><pre></pre></ng-container>
    </ng-container>`,
})
export class LogModalComponent implements OnInit {
  @Input() logContent: string | TemplateRef<{}>;

  constructor() {}

  isTemplateRef (logContent) {
    return logContent instanceof TemplateRef;
  }

  isString (logContent) {
    return typeof(logContent) === 'string';
  }

  ngOnInit(): void {
  }
}

JS类型判断

在JS类型判断的时候需要注意instanceoftypeof, 我的理解typeof可以返回基本数据类型(number、string等),而instanceof用来判断Class。在这一点上跟python就有比较大的区别,在python中都是Class,不论是内置数据类型intstr等,还是自定义的Class,都可以使用isinstance来判断实例的类型。

所以在TS(或JS)中判断是否为字符串等基本数据类型不能使用instanceof,要这样写

typeof(logContent) === 'string'

NgTemplateOutlet还可以为tmeplate传入变量

https://angular.io/api/common/NgTemplateOutlet

Usage notes

<ng-container *ngTemplateOutlet="templateRefExp; context: contextExp"></ng-container>

Using the key $implicit in the context object will set its value as default.

Example

@Component({
  selector: 'ng-template-outlet-example',
  template: `
    <ng-container *ngTemplateOutlet="greet"></ng-container>
    <hr>
    <ng-container *ngTemplateOutlet="eng; context: myContext"></ng-container>
    <hr>
    <ng-container *ngTemplateOutlet="svk; context: myContext"></ng-container>
    <hr>

    <ng-template #greet><span>Hello</span></ng-template>
    <ng-template #eng let-name><span>Hello !</span></ng-template>
    <ng-template #svk let-person="localSk"><span>Ahoj !</span></ng-template>
`
})
class NgTemplateOutletExample {
  myContext = {$implicit: 'World', localSk: 'Svet'};
}