深入淺析ng-bootstrap 組件集中 tabset 組件的實(shí)現(xiàn)分析
ng-bootstrap: tabset
本文介紹了 ng-bootstrap 項(xiàng)目中,tabset 的實(shí)現(xiàn)分析。
使用方式
<ngb-tabset> 作為容器元素,其中的每個(gè)頁(yè)簽以一個(gè) <ngb-tab> 元素定義,在 <ngb-tabset> 中包含若干個(gè) <ngb-tab> 子元素。
在 <ngb-tab> 元素中,使用 <ng-template> 模板來(lái)定義內(nèi)容,內(nèi)容分為兩種:標(biāo)題和內(nèi)容。
標(biāo)題使用 [ngbTabTitle] 指令來(lái)聲明,或者在 <ngb-tab> 元素上使用 title 屬性聲明。
內(nèi)容使用 [ngbTabContent] 指令聲明。
<ngb-tabset> <ngb-tab title="Simple"> <ng-template ngbTabContent> <p>Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.</p> </ng-template> </ngb-tab> <ngb-tab> <ng-template ngbTabTitle><b>Fancy</b> title</ng-template> <ng-template ngbTabContent>Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. <p>Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.</p> </ng-template> </ngb-tab> <ngb-tab title="Disabled" [disabled]="true"> <ng-template ngbTabContent> <p>Sed commodo, leo at suscipit dictum, quam est porttitor sapien, eget sodales nibh elit id diam. Nulla facilisi. Donec egestas ligula vitae odio interdum aliquet. Duis lectus turpis, luctus eget tincidunt eu, congue et odio. Duis pharetra et nisl at faucibus. Quisque luctus pulvinar arcu, et molestie lectus ultrices et. Sed diam urna, egestas ut ipsum vel, volutpat volutpat neque. Praesent fringilla tortor arcu. Vivamus faucibus nisl enim, nec tristique ipsum euismod facilisis. Morbi ut bibendum est, eu tincidunt odio. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris aliquet odio ac lorem aliquet ultricies in eget neque. Phasellus nec tortor vel tellus pulvinar feugiat.</p> </ng-template> </ngb-tab> </ngb-tabset>
可以看到,外層元素是 <ngb-tabset>。
每個(gè) tab 使用元素 <ngb-tab> 定義,tab 的內(nèi)容使用 <ng-template> 模板定義, tab 中的內(nèi)容分為兩個(gè)部分:標(biāo)題和內(nèi)容。
下面是使用模板的標(biāo)題
<ng-template ngbTabTitle><b>Fancy</b> title</ng-template>
標(biāo)題也可以在 ngb-tab 上使用 [title] 屬性定義。例如:
<ngb-tab title="Disabled" [disabled]="true">
內(nèi)容部分定義,這里使用了指令 [ngbTabContent] 便于識(shí)別。
<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 元素的內(nèi)容,它們?cè)谑褂脮r(shí)定義,而不是在 ngb-tabse 自己的模板中定義。
所以找到它們需要使用 ContentChildren 來(lái)找到。
@ContentChildren(NgbTab) tabs: QueryList<NgbTab>;
不使用 ContentChild 的原因是它沒(méi)有提供 descendants 的支持。
在 bootstrap 中,每個(gè)頁(yè)簽 實(shí)際上渲染成兩個(gè)部分,一個(gè)標(biāo)題的列表,和當(dāng)前顯示的內(nèi)容。
標(biāo)題列表使用一個(gè) ul 來(lái)處理。其中使用循環(huán)來(lái)將所有的標(biāo)題顯示出來(lái)。
而 titleTpl 是由模板定義的,所以,使用了 [ngTemplateOutlet] 來(lái)渲染出來(lái)。
<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 部分并列使用了兩種來(lái)源
{{tab.title}}<ng-template [ngTemplateOutlet]="tab.titleTpl?.templateRef"></ng-template>
內(nèi)容部分,由于具體內(nèi)容也是使用模板定義出來(lái),所以這里也是使用 [ngTemplateOutlet] 渲染出來(lái)。
<div class="tab-content">
<ng-template ngFor let-tab [ngForOf]="tabs">
<div
class="tab-pane {{tab.id === activeId ? 'active' : null}}"
*ngIf="!destroyOnHide || tab.id === activeId"
role="tabpanel"
[attr.aria-labelledby]="tab.id" id="{{tab.id}}-panel">
<ng-template [ngTemplateOutlet]="tab.contentTpl?.templateRef"></ng-template>
</div>
</ng-template>
</div>
投影內(nèi)容需要在 Content 類型的事件中處理。
ngAfterContentChecked() {
// auto-correct activeId that might have been set incorrectly as input
let activeTab = this._getTabById(this.activeId);
this.activeId =
activeTab ? activeTab.id : (this.tabs.length ? this.tabs.first.id : null);
}
兩個(gè)指令定義
指令的定義非常簡(jiǎn)單,就是獲取模板的引用,以便后繼使用。
可以看到屬性名稱為 templateRef
@Directive({selector: 'ng-template[ngbTabTitle]'})
export class NgbTabTitle {
constructor(public templateRef: TemplateRef<any>) {}
}
這是 [ngbTabContent] 的定義,與上面相同,依然是定義了屬性 templateRef。
@Directive({selector: 'ng-template[ngbTabContent]'})
export class NgbTabContent {
constructor(public templateRef: TemplateRef<any>) {}
}
Tab 定義
元素型的指令,所以連模板都沒(méi)有了。
@Directive({selector: 'ngb-tab'})
內(nèi)容是投影進(jìn)來(lái)的。
由于在 tab 中使用了模板,并且使用指令來(lái)標(biāo)識(shí)出來(lái),它們定義在組件的模板之內(nèi),所以這里使用了 ContentChildren 來(lái)識(shí)別。
@ContentChildren(NgbTabTitle, {descendants: false}) titleTpls: QueryList<NgbTabTitle>;
@ContentChildren(NgbTabContent, {descendants: false}) contentTpls: QueryList<NgbTabContent>
以后就可以使用 titleTpls 和 contentTpls 來(lái)使用模板了。
由于是內(nèi)容,需要在 content 的事件中處理,實(shí)際上,在每個(gè)頁(yè)簽中,我們只有一個(gè)標(biāo)題和一個(gè)內(nèi)容的聲明。
ngAfterContentChecked() {
// We are using @ContentChildren instead of @ContentChild as in the Angular version being used
// only @ContentChildren allows us to specify the {descendants: false} option.
// Without {descendants: false} we are hitting bugs described in:
// https://github.com/ng-bootstrap/ng-bootstrap/issues/2240
this.titleTpl = this.titleTpls.first;
this.contentTpl = this.contentTpls.first;
}
See also
總結(jié)
以上所述是小編給大家介紹的深入淺析ng-bootstrap 組件集中 tabset 組件的實(shí)現(xiàn)分析,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
在一個(gè)頁(yè)面實(shí)現(xiàn)兩個(gè)zTree聯(lián)動(dòng)的方法
最近發(fā)現(xiàn)項(xiàng)目中很多地方都是樹(shù)形菜單,而這些樹(shù)形菜單都是使用樹(shù)形插件zTree來(lái)制作的,下面這篇文章主要給大家介紹了關(guān)于在一個(gè)頁(yè)面實(shí)現(xiàn)兩個(gè)zTree聯(lián)動(dòng)的相關(guān)資料,需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-12-12
基于jquery的從一個(gè)頁(yè)面跳轉(zhuǎn)到另一個(gè)頁(yè)面的指定位置的實(shí)現(xiàn)代碼(帶平滑移動(dòng)的效果)
從一個(gè)頁(yè)面跳轉(zhuǎn)到另一個(gè)頁(yè)面的指定位置 如果不帶平滑移動(dòng)的效果 很容易 加個(gè) 錨點(diǎn)就行了2011-05-05
jQuery實(shí)現(xiàn)的網(wǎng)頁(yè)豎向菜單效果代碼
這篇文章主要介紹了jQuery實(shí)現(xiàn)的網(wǎng)頁(yè)豎向菜單效果代碼,涉及jquery控制頁(yè)面元素簡(jiǎn)單折疊與展開(kāi)功能,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-08-08
JQuery對(duì)ASP.NET MVC數(shù)據(jù)進(jìn)行更新刪除
這篇文章主要介紹了JQuery對(duì)ASP.NET MVC數(shù)據(jù)進(jìn)行更新刪除的相關(guān)資料,需要的朋友可以參考下2016-07-07
jQuery+ajax實(shí)現(xiàn)動(dòng)態(tài)添加表格tr td功能示例
這篇文章主要介紹了jQuery+ajax實(shí)現(xiàn)動(dòng)態(tài)添加表格tr td功能,結(jié)合實(shí)例形式分析了jQuery基于ajax動(dòng)態(tài)創(chuàng)建頁(yè)面table元素相關(guān)操作技巧,需要的朋友可以參考下2018-04-04
jQuery.cookie.js使用方法及相關(guān)參數(shù)解釋
一個(gè)輕量級(jí)的cookie 插件,可以讀取、寫入、刪除 cookie。這篇文章主要介紹了jQuery.cookie.js使用方法及相關(guān)參數(shù)解釋,需要的朋友可以參考下2017-03-03
使用Javascript實(shí)現(xiàn)選擇下拉菜單互移并排序
本文給大家介紹使用js實(shí)現(xiàn)下拉菜單可選擇互相移動(dòng)并實(shí)現(xiàn)菜單排序,代碼簡(jiǎn)單易懂,具有參考價(jià)值,需要的朋友參考下吧2016-02-02

