Angular ng-content 使用选择时的不同行为

卢卡·萨姆哈拉泽

正如我们所知,仅在最后匹配的 ng-content 中使用 ng-content 项目内容,但我不明白的是,为什么在仅将 select 和项目用于第一个时它的行为相反。

第一个子组件

1
<ng-content select=".my-class"></ng-content> <br>
2
<ng-content select=".my-class"></ng-content>

第二个子组件

1
<ng-content></ng-content> <br>
2
<ng-content></ng-content>

父组件

<app-first>
    <ng-container class="my-class">CHILD</ng-container>
</app-first>

<br>--------<br>

<app-second>
    <ng-container class="my-class">CHILD</ng-container>
</app-second>

结果

1 CHILD
2
--------
1
2 CHILD

闪电战

yurzui

Angular 编译器计算所谓的ngContentIndex. 您可以将其视为应该投影嵌入节点的地方。

所以,有AppComponent模板

<app-first>
    <ng-container class="my-class">CHILD</ng-container>
</app-first>

<br>--------<br>

<app-second>
    <ng-container class="my-class">CHILD</ng-container>
</app-second>  

Angular 为每个节点提供了它的ngContentIndex(看看括号):

<app-first>(null)
    <ng-container class="my-class">CHILD</ng-container>(1)
</app-first>

<br>--------<br>(null)

<app-second>(null)
    <ng-container class="my-class">CHILD</ng-container>(0)
</app-second>  

这意味着第一个CHILD应该转到第二个 ng-content,第二个应该转到CHILD第一个。

为什么会这样?

答案在于 Angular 编译器的源代码。

默认情况下<ng-content></ng-content>

<ng-content select="*"></ng-content>

对于每个模板,Angular 都知道它的所有内容ngContentSelectors

FirstComponent ['*', '*']

SecondComponent ['.my-class', '.my-class']

这是答案

const ngContentSelectors = component.directive.template !.ngContentSelectors;
for (let i = 0; i < ngContentSelectors.length; i++) {
  const selector = ngContentSelectors[i];
  if (selector === '*') {
    wildcardNgContentIndex = i;
  } else {
    matcher.addSelectables(CssSelector.parse(ngContentSelectors[i]), i);
  }
}

您可以看到 Angular 进行了*特殊处理wildcardNgContentIndex在循环中更新,因此它将是1. 对于['.my-class', '.my-class']数组,它将选择器添加到匹配项。

最后,Angular 使用这种方法

findNgContentIndex(selector: CssSelector): number | null {
  const ngContentIndices: number[] = [];
  this._ngContentIndexMatcher.match(selector, (selector, ngContentIndex) => {
    ngContentIndices.push(ngContentIndex);
  });
  ngContentIndices.sort();
  if (this._wildcardNgContentIndex != null) {
    ngContentIndices.push(this._wildcardNgContentIndex);
  }
  return ngContentIndices.length > 0 ? ngContentIndices[0] : null;
}

这将返回 中1可投影节点的保存FirstComponent

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章