* ngTemplateOutlet指令的实际方案是什么?

pat*_*729 7 directive ng-template angular

我正在阅读有关*ngTemplateOutlet指令的信息。此伪指令的使用是通过模板引用和上下文对象作为参数来动态实例化模板。

我想知道的是,我们在Angular中有很多东西可以实现与* ngTemplateOutlet相同的结果,例如:

  1. 我们可以有多个*ngIf可以基于相同组件中的组件变量值呈现不同的模板。我们以类似的方式[ngSwitch]根据不同的值为我们呈现不同的模板。

  2. 我们可以通过引用*ngIf相应变量的模板引用变量来使用引用。

对于前一种情况:

<div *ngIf="condition1"> Content 1 </div>
<div *ngIf="condition2"> Content 2 </div>
<div *ngIf="condition3"> Content 3 </div>
Run Code Online (Sandbox Code Playgroud)

对于后者:

<ng-container *ngIf="condition then myTemplate else otherTemplate"></ng-container>
<ng-template #myTemplate> Some content... </ng-template>
<ng-template #otherTemplate> Some content... </ng-template>
Run Code Online (Sandbox Code Playgroud)

如果我们的武器库中有这种方法,那么还能*ngTemplateOutlet增加更多的价值?

有哪些实际用例(如果有的话)不能使用上述方法,而应使用*ngTemplateOutlet指令,还是选择另一种方法来获得相同的结果?

Ste*_*per 13

使 *ngTemplateOutlet 比 *ng-content 更强大的一件事是当您将它与 [ngTemplateOutletContext] 输入一起使用时。这使您能够创建一个完全独特的模板,该模板可以使用组件内的状态。

我已经使用它创建了一个选择组件,该组件通过不同的模板为每个客户设计了独特的样式,但共享完全相同的代码。这是一个StackBlitz 链接,也是我在indepth.dev上关于它的文章。

*ngTemplateOutlets 比使用 *ngIfs 的好处的一个例子是你的组件不需要依赖外部包,即图标库,如果它只被一个客户端使用。


Con*_*Fan 7

角度模板出口可用于在视图的各个部分中插入通用模板,这些模板不是由循环生成或受条件约束的。例如,您可以定义公司徽标的模板,然后将其插入页面中的多个位置:

<div>
  <ng-container *ngTemplateOutlet="companyLogoTemplate"></ng-container>
  <h1>Company History</h1>
  <div>{{companyHistory}}</div>
</div>
<form (ngSubmit)="onSubmit()">
  <ng-container *ngTemplateOutlet="companyLogoTemplate"></ng-container>
  <h1>User info</h1>
  <label>Name:</label><input type="text" [(ngModel)]="userName" />
  <label>Account ID:</label><input type="text" [(ngModel)]="accountId" />
  <button>Submit</button>
</form>
<div class="footer">
  <ng-container *ngTemplateOutlet="companyLogoTemplate"></ng-container>
</div>

<ng-template #companyLogoTemplate>
  <div class="companyLogo">
    <img [src]="logoSourceUrl">
    <label>The ACME company, {{employeeCount}} people working for you!</label>
  </div>
</ng-template>
Run Code Online (Sandbox Code Playgroud)

模板和模板出口还可以帮助使组件可配置。下面的例子是取自本文角大学

选项卡容器组件定义了默认的选项卡头模板,但允许使用定义为输入属性的自定义模板覆盖它。然后,将适当的模板(默认模板或自定义模板)插入带有模板出口的视图中:

@Component({
  selector: 'tab-container',
  template: `
    <ng-template #defaultTabButtons>
      <div class="default-tab-buttons">
        ...
      </div>
    </ng-template>
    <ng-container *ngTemplateOutlet="headerTemplate || defaultTabButtons"></ng-container>
    ... rest of tab container component ...
  `
})
export class TabContainerComponent {
    @Input() headerTemplate: TemplateRef<any>; // Custom template provided by parent
}
Run Code Online (Sandbox Code Playgroud)

在父组件中,定义自定义选项卡标题模板并将其传递给选项卡容器组件:

@Component({
  selector: 'app-root',
  template: `      
    <ng-template #customTabButtons>
      <div class="custom-class">
        <button class="tab-button" (click)="login()">
          {{loginText}}
        </button>
        <button class="tab-button" (click)="signUp()">
          {{signUpText}}
        </button>
      </div>
    </ng-template>
    <tab-container [headerTemplate]="customTabButtons"></tab-container>      
  `
})
export class AppComponent implements OnInit {
  ...
}
Run Code Online (Sandbox Code Playgroud)

您可以在此博客中通过alligator.io查看另一个高级用例。


Sun*_*ngh 5

您有一个非常有效的问题。如果通过简单ifswitch案例可以实现某些目标,为什么要使用*ngTemplateOutlet

独立组件

您之所以会想到这些,是因为您正在考虑一个独立的组件级别。换句话说,所有条件,模板都在同一组件中。我们可以根据特定条件轻松选择模板。

库组件

动态模板

当我说库组件,这意味着通用的可重用组件前AutocompleterTypeahead等这些组件提供的功能部分。然而,他们允许开发者选择自己template按照自己的需求。

现在是问题所在,这些模板不存在Autocompleter,而是来自@ContentChild

例如:

<ng-autocompleter>
   <ng-template #item let-item>{{item.name}}</ng-template>
<ng-autocompleter>
Run Code Online (Sandbox Code Playgroud)

在上面的示例<ng-template>中,定义了开发人员稍后的时间,而不是的直接部分<ng-autocompleter>

模板上下文

每当开发高度配置的组件时,模板上下文就非常重要。获得动态模板(html)不足以达到目的。我们需要将值绑定到ng-template。由于ng-template不在其中,ng-autocompleter我们需要传递包含所有需要绑定的数据的上下文。

ex:在上述情况下,如果您看到我们通过声明了item变量,let-item但变量的来源item是哪里。那将取决于给定的上下文*ngTemplateOutlet

一句话结论如果我们要注入将来将由某人声明的模板,那么我无法通过* ngIf或* ngSwitch处理这种情况。我们需要使用*ngTemplateOutlet