深入浅析ng-bootstrap 组件集中 tabset 组件的实现分析

2020-05-16 18:42:48易采站长站整理

</ng-template>
</ngb-tab>
</ngb-tabset>

可以看到,外层元素是

 <ngb-tabset>

每个 tab 使用元素

 <ngb-tab>
定义,tab 的内容使用
 <ng-template> 
模板定义, tab 中的内容分为两个部分:标题和内容。

下面是使用模板的标题


<ng-template ngbTabTitle><b>Fancy</b> title</ng-template>

标题也可以在 ngb-tab 上使用 [title] 属性定义。例如:


<ngb-tab title="Disabled" [disabled]="true">

内容部分定义,这里使用了指令

 [ngbTabContent]
便于识别。


<ng-template ngbTabContent>
<p>Sed commodo, leo at suscipit dictum, quam est porttitor sapien, eget sodales nibh elit id diam.
</p>
</ng-template>

TabSet 组件定义

从前面的使用可以看出,所有 tab 的定义都是 ngb-tabset 元素的内容,它们在使用时定义,而不是在 ngb-tabse 自己的模板中定义。

所以找到它们需要使用 ContentChildren 来找到。

@ContentChildren(NgbTab) tabs: QueryList<NgbTab>;

不使用 ContentChild 的原因是它没有提供 descendants 的支持。

在 bootstrap 中,每个页签 实际上渲染成两个部分,一个标题的列表,和当前显示的内容。

标题列表使用一个 ul 来处理。其中使用循环来将所有的标题显示出来。

而 titleTpl 是由模板定义的,所以,使用了

 [ngTemplateOutlet] 
来渲染出来。


<ul [class]="'nav nav-' + type + (orientation == 'horizontal'? ' ' + justifyClass : ' flex-column')" role="tablist">
<li class="nav-item" *ngFor="let tab of tabs">
<a [id]="tab.id" class="nav-link"
[class.active]="tab.id === activeId"
[class.disabled]="tab.disabled"
href (click)="select(tab.id); $event.preventDefault()"
role="tab"
[attr.tabindex]="(tab.disabled ? '-1': undefined)"
[attr.aria-controls]="(!destroyOnHide || tab.id === activeId ? tab.id + '-panel' : null)"
[attr.aria-selected]="tab.id === activeId" [attr.aria-disabled]="tab.disabled">
{{tab.title}}<ng-template [ngTemplateOutlet]="tab.titleTpl?.templateRef"></ng-template>
</a>
</li>
</ul>

title 部分并列使用了两种来源


{{tab.title}}<ng-template [ngTemplateOutlet]="tab.titleTpl?.templateRef"></ng-template>