【问题标题】:Can an angular component be identified within an HTML element?可以在 HTML 元素中识别角度组件吗?
【发布时间】:2020-01-01 04:16:31
【问题描述】:

我想创建一个表格过滤器组件,它符合 Angular Material 中 matSort/mat-sort-header 组件的结构和语法。它的创建方式是将matSort 指令放在<table> 元素上,然后对于要排序的每一列,放置mat-sort-header 指令。然而,有趣的是,没有给定mat-sort-header 指令元素的列只不过是<th> 中的文本,而具有mat-sort-header 指令的列则使该列(包含包含的文本)变为变成一个按钮。

我查看了@angular/material/sorthttps://github.com/angular/components/blob/master/src/material/sort/sort-header.html)的源代码,发现mat-sort-header实际上被修饰为@Component,而不是@Directive,并带有自己的模板。但是,这有点违背我对组件的理解。我知道 Component is 是一个指令,但我不知道您可以将指令放在原生 HTML 元素中并让内部结构生成 HTML。

以下是创建可排序表头的方法:

<table mat-table [dataSource]="dataSource" matSort class="mat-elevation-z8">

  <!-- Position Column -->
  <ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> No. </th>
    <td mat-cell *matCellDef="let element"> {{element.position}} </td>
  </ng-container>
 ...

我将 mat-sort-header 作为属性指令读取,但源代码显示它是一个 组件指令。这是在任何地方的文档中吗?这可行吗?

同样,如果我想创建自己的过滤器/排序组件来与这种结构平行,Angular 支持吗?

【问题讨论】:

  • 您还可以在MatDatepicker's code 上找到它,其中mat-calendar-body selector 引入了所有表格主体(tr's 和td's)。
  • 谢谢!我只是在他们的文档中错过了这一点吗?这回答了我关于创建可以合并到角材料中的组件的许多问题。

标签: html angular angular-material components


【解决方案1】:

所有指令都是底层组件。这都是关于装饰者的。指令装饰器让编译器知道您不会使用模板,并且您将通常使用组件来更改 DOM 布局或更改元素的外观或行为。 (参见:link)。

mat-sort-header 仍然是一个组件,它有一个模板,它只是通过一个属性被选中。这可以在selector: [mat-sort-header] 中看到。他们也可以让它成为一个指令,但是因为他们需要视图/样式,所以它需要成为一个组件。

【讨论】:

  • 我以为是反过来的,所有组件都是指令(文档说这三种类型是结构、属性和组件)。
  • 我必须澄清我的问题,并为不明确表示歉意。问题是组件,根据文档,我认为是 THE 元素,所以看到像 这样的东西会让我对 angular 可能发生的事情失去理解。如果 mat-table-header 是模板,那么 angular 如何确定在模板中的位置?似乎这种用法进一步扩展了能力,所以我不确定为什么文档中没有更清楚。
  • 就 Angular 而言,是的,你是对的。 Angular 将它们的组件标记为指令。但在所有其他框架/网络标准中,它们被称为组件。
  • 你在第一次回复中回答了你自己的问题!组件只是带有模板的指令。您的指令元数据确定它是否具有模板。 @Component 具有“template”或“templateUrl”的属性,@Directive 没有。可以通过元素或属性选择组件。通常的选择器是作为一个元素,并且是根据 Angular 样式指南的首选方式。指令作为属性。但是你有一个可以通过元素或属性选择的组件!
  • 非常感谢您的回答和帮助,这是我无法弄清楚的断开连接。
【解决方案2】:

我在这里的困惑是假设,去计算。

在我的原始帖子中,我将代码显示为

<ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef mat-sort-header> No. </th>
    <td mat-cell *matCellDef="let element"> {{element.position}} </td>
</ng-container>

但我也看到它写成

<ng-container matColumnDef="position">
    <mat-header-cell *matHeaderCellDef mat-sort-header> No. </th>
    <mat-cell *matCellDef="let element"> {{element.position}} </td>
</ng-container>

(注意缺少的th 元素)。

正是我看到的第二个问题引发了我的问题,在我脑海中反复思考之后,我得出了一个(不正确的)结论,即mat-header-cell 是一个组件。这没有意义,两个组件怎么可能存在于同一个元素中?毕竟是 Angular 自己说的here

Angular 组件是指令的子集,总是与 一个模板。与其他指令不同,只有一个组件可以 每个模板中的元素实例化。

所以我四处挖掘以实现以下两个目标之一:更好地理解 Angular,或者证明 Angular 在撒谎。查看表格源代码,documentation 表明mat-header-cell 实际上是一个指令,并且可以使用两个可能的选择器来识别它。

/** Header cell template container that adds the right classes and role. */
@Directive({
  selector: 'mat-header-cell, th[mat-header-cell]',
  host: {
    'class': 'mat-header-cell',
    'role': 'columnheader',
  },
})
export class MatHeaderCell extends CdkHeaderCell {
  constructor(columnDef: CdkColumnDef,
              elementRef: ElementRef<HTMLElement>) {
    super(columnDef, elementRef);
    elementRef.nativeElement.classList.add(`mat-column-${columnDef.cssClassFriendlyName}`);
  }
}

哎呀……

这意味着顶部的行仍然只包含一个组件。所以一切都完好无损,Angular 非常诚实,我学到了一些东西。开源万岁!

每个人都保留你的分数和答案,我只是想澄清我为什么问,以及在我的大脑中发生的最后一次点击是有意义的。

【讨论】:

    猜你喜欢
    相关资源
    最近更新 更多
    热门标签