緣起
今天會講這個主題,主要是之前看到很多框架的元件裡面都會有這樣的做法
以下範例取自 ngx-admin 的 nebular 專案,有興趣的讀者可以去看一下它的專案
1 2 3 4 5 6 7 8
| <nb-tabset> <nb-tab tabTitle="Simple Tab #1"> Tab content 1 </nb-tab> <nb-tab tabTitle="Simple Tab #2"> Tab content 2 </nb-tab> </nb-tabset>
|
那實際上這是怎麼樣達成的呢?
我們先從裡面看到外面,因為這個元件同時用到了 單一內容投影
, 多筆內容投影
裡面因為稍微單純一點就從裡面開始說!
NbTabComponent
通常看到這種形式,就是你自訂的元件中間包著其他內容,我們就可以猜到他有用到內容投影的技巧,簡單來說你自定的元件標籤中所包起來的那一塊,都會被投影到實際 nb-tab 的元件裡。
1 2 3 4 5 6 7 8 9 10 11 12
| <nb-tabset> <nb-tab tabTitle="Simple Tab #1"> Tab content 1 </nb-tab> <nb-tab tabTitle="Simple Tab #2"> Tab content 2 </nb-tab> </nb-tabset>
|
整塊的 p 標籤會被投到我下面標示的 ng-content 標籤 (ng-content 整個會被取代掉)
1 2 3 4 5 6 7 8 9 10 11
| @Component({ selector: 'nb-tab', template: ` <ng-container *ngIf="init"> <!-- 投影的內容區塊 --> <ng-content></ng-content> <!-- 投影的內容區塊 --> </ng-container> `, }) export class NbTabComponent { ... }
|
NbTabsetComponent
有了上面的概念之後你就知道, nb-tabset 元件裡面包的內容都會投影到
<ng-content select="nb-tab"></ng-content>
這個區塊,唯一不一樣的是,他算是 多筆 的內容投影
所以你會看到 select="ng-tab"
這種特殊的寫法
那是因為他要精確的告訴元件,我要投影的是哪個標籤 or 元素
1 2 3 4 5 6 7 8 9 10
| <nb-tabset> <nb-tab tabTitle="Simple Tab #1"> Tab content 1 </nb-tab> <nb-tab tabTitle="Simple Tab #2"> Tab content 2 </nb-tab> </nb-tabset>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @Component({ selector: 'nb-tabset', styleUrls: ['./tabset.component.scss'], template: ` <ul class="tabset"> <li *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.responsive]="tab.responsive" [class.active]="tab.active" [class.disabled]="tab.disabled" [attr.tabindex]="tab.disabled ? -1 : 0" class="tab"> <a href (click)="$event.preventDefault()" tabindex="-1"> <i *ngIf="tab.tabIcon" [class]="tab.tabIcon"></i> <span *ngIf="tab.tabTitle">{{ tab.tabTitle }}</span> </a> <nb-badge *ngIf="tab.badgeText" [text]="tab.badgeText" [status]="tab.badgeStatus" [position]="tab.badgePosition"> </nb-badge> </li> </ul> <!-- 這個區塊就是要投影所挖的洞 --> <ng-content select="nb-tab"></ng-content> `, }) export class NbTabsetComponent implements AfterContentInit { ... }
|
實例展示
看完了 Angular 的 Content Projection 實際用 stackblitz 練習一下,各位可以點過去玩一下
參考資料