前言

tab 就是可以分頁的標籤

如果有用 Bootstrap,那要用 tab 就會很簡單。

<ul class="nav nav-tabs">
    <li class="active"><a data-toggle="tab" href="#home">Home</a></li>
    <li><a data-toggle="tab" href="#menu1">Menu 1</a></li>
    <li><a data-toggle="tab" href="#menu2">Menu 2</a></li>
    <li><a data-toggle="tab" href="#menu3">Menu 3</a></li>
</ul>

<div class="tab-content">
<div id="home" class="tab-pane fade in active">
<h3>HOME</h3>
<p>…</p>
</div>
<div id="menu1" class="tab-pane fade">
<h3>Menu 1</h3>
<p>…</p>
</div>
<div id="menu2" class="tab-pane fade">
<h3>Menu 2</h3>
<p>…</p>
</div>
<div id="menu3" class="tab-pane fade">
<h3>Menu 3</h3>
<p>…</p>
</div>
</div>

但我們今天用 Angular 2 來硬幹一個!

Tab

實現一個 tab 大概會長這樣

<tabs>
    <tab>
        <p>This Tab Content 1</p>
    </tab>
    <tab>
        <p>This Tab Content 1</p>
    </tab>
    <tab>
        <p>This Tab Content 1</p>
    </tab>
</tabs>

我們並不想寫成這樣

<tabs [contents]="[...]"></tabs>

把所有 tab 的內容當變數傳遞,這會增加閱讀的難度。我們想要的是顯示層次明確的樣子,這樣的話就會用到 @ContentChild 裝飾器。

tab.ts

import {Component,Input} from '@angular/core';

@Component({
selector: 'tab',
template: &lt;p [hidden]=&quot;!show&quot;&gt; &lt;ng-content&gt;&lt;/ng-content&gt; &lt;/p&gt;
})
export class TabComponent {
@Input()
tabTitle:string;

show:boolean = false;

}

tabs.ts

import {Component,ContentChildren,QueryList,AfterContentInit} from '@angular/core';
import {TabComponent} from './tab';

@Component({
selector: 'tabs',
template: &lt;ul class=&quot;tab-list&quot;&gt; &lt;li *ngFor=&quot;let tab of tabs&quot; [class.active]=&quot;selectedTab===tab&quot; (click)=&quot;onSelect(tab)&quot;&gt; {{tab.tabTitle}} &lt;/li&gt; &lt;/ul&gt; &lt;ng-content&gt;&lt;/ng-content&gt; ,
styles: [`
.tab-list{
list-style:none;
overflow:hidden;
padding:0;
color: white;
}

    .tab-list li{
        cursor:pointer;
        float:left;
        width:60px;
        height:30px;
        line-height:30px;
        text-align:center;
        background-color:gray;
    }

    .tab-list li:hover{
        background-color:#424242;
    }
    .tab-list li.active{
        background-color:black;
    }
`]

})
export class TabsComponent implements AfterContentInit {
@ContentChildren(TabComponent)
tabs:QueryList<TabComponent>;

selectedTab:TabComponent;

ngAfterContentInit() {
    this.select(this.tabs.first);
}

onSelect(tab) {
    this.select(tab);
}

select(tab) {
    this.tabs.forEach((item)=&gt;{
        item.show = false;
    });

    this.selectedTab = tab;
    this.selectedTab.show = true;
}

}

app.ts

import {Component,ContentChildren,QueryList} from '@angular/core';
import {TabsComponent} from './tabs';
import {TabComponent} from './tab';

@Component({
selector: 'my-app',
template: &lt;h2&gt;App Component&lt;/h2&gt; &lt;tabs&gt; &lt;tab tabTitle=&quot;First&quot;&gt; &lt;p&gt;This Tab Content 1&lt;/p&gt; &lt;/tab&gt; &lt;tab tabTitle=&quot;Second&quot;&gt; &lt;p&gt;This Tab Content 2&lt;/p&gt; &lt;/tab&gt; &lt;tab tabTitle=&quot;third&quot;&gt; &lt;p&gt;This Tab Content 3&lt;/p&gt; &lt;/tab&gt; &lt;/tabs&gt; ,
directives: [TabsComponent,TabComponent]
})
export class AppComponent {
}

範例

Plunker