【问题标题】:Clean way of checking if value is in an array in Angular Template检查值是否在Angular模板中的数组中的干净方法
【发布时间】:2020-02-27 06:04:53
【问题描述】:

我正在制作一个 Angular 组件,该组件将用于根据输入字符串显示文件图标。将根据每个文件类型的一些可能值的数组检查输入字符串。

例如,

  • 如果我们看到 doc、docx、word,则显示 word 图标。
  • 如果我们看到 xls、xlsx、excel,则显示 excel 图标。

等等,对于我们的应用程序期望的每种文件类型。

我正计划根据输入字符串所在的数组创建一个带有适当类的 <i> 元素的简单列表。

export class FileIconComponent {
  @Input() fileType: string;

  private readonly FILE_WRD: string[] = ["word", "doc", "docx"];
  private readonly FILE_PDF: string[] = ["pdf", "application/pdf"];
  private readonly FILE_EXL: string[] = ["excel", "xls", "xlsx"];

  constructor() {}
}
<i *ngIf="FILE_EXL.includes(fileType?.toLowerCase())" class="icon document-excel-o"></i>
<i *ngIf="FILE_WRD.includes(fileType?.toLowerCase())" class="icon document-word-o"></i>
<i *ngIf="FILE_PPT.includes(fileType?.toLowerCase())" class="icon document-powerpoint-o"></i>

但是,由于更改检测每秒运行很多次,并且我可能每页显示一百行,所以当我在模板中放置函数调用时,我担心性能。制作一个 &lt;i&gt; 并使用 ngClass 来确定类会更高效吗?

有没有更有效的方法来做到这一点?还是我在这种情况下过度关注性能?

【问题讨论】:

标签: angular


【解决方案1】:

Endeed,不建议使用 Angular 生命周期中的 HTML 函数。

在您的情况下,您不能使用 getter 函数,因为结果将取决于索引的值。

为了提高性能,您可以:

  • 为您的组件使用OnPush 策略。
  • 使用trackBypipe 不要每次都重新加载所有列表。
  • ngOnChanges 的对象中添加一个字段,您可以在其中为每个项目指定所需的类以避免使用函数。
  • 正如@bryan60 所建议的那样,您可以使用ngOnChanges 的替代方法,即setter 输入方法。

【讨论】:

  • setter 输入通常优于 ngOnChanges 生命周期钩子
  • @bryan60,你说得对,只有一个@Input(),setter 很有趣。但我不是 setter 中使用的“私有”幽灵属性的忠实粉丝。
【解决方案2】:

您可以添加一个 Enum,并在 ngIf 中使用它

import { Component, Input, OnInit } from "@angular/core";

enum FileTypeEnum {
  FILE_WRD,
  FILE_PDF,
  FILE_EXL
}

@Component({
  selector: "hello",
  template: `
    <i *ngIf="type === fileTypeEnum.FILE_EXL" class="icon document-excel-o"></i>
    <i *ngIf="type === fileTypeEnum.FILE_WRD" class="icon document-word-o"></i>
    <i *ngIf="type === fileTypeEnum.FILE_PDF" class="icon document-pdf-o"></i>
  `,
  styles: [
    `
      h1 {
        font-family: Lato;
      }
    `
  ]
})
export class HelloComponent implements OnInit {
  @Input() name: string;
  type: FileTypeEnum;
  fileTypeEnum = FileTypeEnum;
  private readonly fileTypes = {
    FILE_WRD: ["word", "doc", "docx"],
    FILE_PDF: ["pdf", "application/pdf"],
    FILE_EXL: ["excel", "xls", "xlsx"]
  };

  ngOnInit() {
    const fileType = Object.keys(this.fileTypes).find(key => this.fileTypes[key].includes(this.name));
    this.type = FileTypeEnum[fileType];
  }
}

但如果这个逻辑只是为了知道显示哪个图标,那么你可以使用 ngClass 来代替只有一个i 标签:

import { Component, Input, OnInit } from "@angular/core";

@Component({
  selector: "hello",
  template: `
    <i [ngClass]="className"></i>
  `,
  styles: [
    `
      h1 {
        font-family: Lato;
      }
    `
  ]
})
export class HelloComponent implements OnInit {
  @Input() name: string;
  className;
  private readonly fileTypes = {
    word: ["word", "doc", "docx"],
    pdf: ["pdf", "application/pdf"],
    excel: ["excel", "xls", "xlsx"]
  };

  ngOnInit() {
    const fileType = Object.keys(this.fileTypes).find(key =>
      this.fileTypes[key].includes(this.name)
    );
    this.className = `icon document-${fileType}-o`;
  }
}

【讨论】:

  • 放置逻辑来确定在ngOnInit中显示哪个图标意味着逻辑只会被调用一次:当组件初始化时。如果输入改变,图标不会更新。起初我也想过同样的事情,但排除了这种方法,因为它根本不处理变更检测。
【解决方案3】:

使用 setter 输入,以便在需要时运行函数....

export class FileIconComponent {
  private _fileType: string;
  @Input() set fileType(fileType: string) {
    this._fileType = fileType;
    this.isWord = this.FILE_WRD.includes(fileType.toLowerCase());
    this.isExcel = this.FILE_EXL.includes(fileType.toLowerCase());
    this.isPdf = this.FILE_PDF.includes(fileType.toLowerCase());
  };
  get fileType() { return this._fileType; }

  isWord = false;
  isExcel = false;
  isPdf = false;

  private readonly FILE_WRD: string[] = ["word", "doc", "docx"];
  private readonly FILE_PDF: string[] = ["pdf", "application/pdf"];
  private readonly FILE_EXL: string[] = ["excel", "xls", "xlsx"];

  constructor() {}
}

然后在模板中简单干净的使用:

<i *ngIf="isExcel" class="icon document-excel-o"></i>
<i *ngIf="isWord" class="icon document-word-o"></i>
<i *ngIf="isPdf" class="icon document-powerpoint-o"></i>

setter 仅在输入更改时运行,因此仅在需要时运行。

【讨论】:

  • 呵呵,有意思,我不知道你可以为输入值定义一个setter函数。
  • 是的,它们很有用。您甚至可以通过找出设置器中的图标类并执行 [ngClass]="iconClass" 并只使用单个图标指令来清理它
  • 是的,这正是我正在做的。在 setter 中设置类名,只需一个 &lt;i [ngClass]="className"&gt;&lt;/i&gt;
  • 太好了,很高兴我能帮上忙。将来肯定更容易将这种方式扩展到更多图标类
猜你喜欢
  • 1970-01-01
  • 2014-10-26
  • 2011-09-07
  • 2014-02-03
  • 1970-01-01
  • 2020-08-27
  • 1970-01-01
  • 2018-05-03
  • 2017-12-09
相关资源
最近更新 更多