ng-content

Angular 與 Content Projection 指南

基本概念

ng-content 是 Angular 中用於內容投影(Content Projection)的指令,允許將外部內容投影到組件的特定位置。

可以用 select 來指定什麼樣的內容要放在這個 content 裡面。尤其當一個 component 裡面有多個 ng-content的時候尤其重要。

基礎用法

最簡單的 ng-content 使用:

// simple-card.component.ts
@Component({
  selector: 'app-simple-card',
  template: `
    <div class="card">
      <ng-content></ng-content>
    </div>
  `
})
export class SimpleCardComponent { }

使用方式:

<app-simple-card>
  <h2>這是標題</h2>
  <p>這是內容</p>
</app-simple-card>

Select 選擇器

1. 使用 CSS 類選擇器

// card.component.ts
@Component({
  selector: 'app-card',
  template: `
    <div class="card">
      <header>
        <ng-content select=".card-title"></ng-content>
      </header>
      <div class="content">
        <ng-content select=".card-content"></ng-content>
      </div>
      <footer>
        <ng-content select=".card-footer"></ng-content>
      </footer>
    </div>
  `
})
export class CardComponent { }

使用方式:

<app-card>
  <h2 class="card-title">卡片標題</h2>
  <div class="card-content">
    <p>這是卡片的主要內容</p>
  </div>
  <div class="card-footer">
    <button>確認</button>
  </div>
</app-card>

2. 使用元素選擇器

// panel.component.ts
@Component({
  selector: 'app-panel',
  template: `
    <div class="panel">
      <ng-content select="header"></ng-content>
      <ng-content select="main"></ng-content>
      <ng-content select="footer"></ng-content>
    </div>
  `
})
export class PanelComponent { }

使用方式:

<app-panel>
  <header>面板標題</header>
  <main>面板內容</main>
  <footer>面板底部</footer>
</app-panel>

3. 使用屬性選擇器

// fancy-button.component.ts
@Component({
  selector: 'app-fancy-button',
  template: `
    <button class="fancy-btn">
      <ng-content select="[icon]"></ng-content>
      <ng-content select="[label]"></ng-content>
      <ng-content select="[suffix]"></ng-content>
    </button>
  `
})
export class FancyButtonComponent { }

使用方式:

<app-fancy-button>
  <i icon class="fas fa-star"></i>
  <span label>點擊我</span>
  <i suffix class="fas fa-arrow-right"></i>
</app-fancy-button>

4. 使用組合選擇器

// list.component.ts
@Component({
  selector: 'app-list',
  template: `
    <div class="list">
      <ng-content select="li[important]"></ng-content>
      <ng-content select="li"></ng-content>
    </div>
  `
})
export class ListComponent { }

使用方式:

<app-list>
  <li important>重要項目</li>
  <li>普通項目 1</li>
  <li>普通項目 2</li>
</app-list>

最佳實踐

  1. 選擇器優先順序:

    • 具體的選擇器應該放在前面

    • 通用的選擇器放在後面

    • 未指定 select 的 ng-content 放在最後

  2. 性能考慮:

    • 避免過多的 ng-content

    • 合理組織選擇器結構

    • 考慮使用 ngTemplateOutlet 處理複雜的情況

  3. 使用時機:

    • 當組件需要靈活的內容結構時

    • 需要複用組件樣式但內容不同時

    • 創建通用UI組件時

Last updated