:host 選擇器

:host 基本概念

:host 選擇器用於定義元件本身(宿主元素)的樣式。簡單來說,就是可以為你的自定義元件加上樣式。

常見用法

1. 基本樣式設定

@Component({
  selector: 'app-card',
  template: `
    <div class="content">
      <ng-content></ng-content>
    </div>
  `,
  styles: [`
    :host {
      display: block;
      border: 1px solid #ccc;
      border-radius: 4px;
      padding: 16px;
    }
  `]
})

使用時:

<app-card>
  這個內容會被包在一個有邊框的卡片中
</app-card>

2. 互動狀態

@Component({
  styles: [`
    :host {
      display: block;
      padding: 8px;
      cursor: pointer;
    }

    :host:hover {
      background: #f0f0f0;
    }

    :host:active {
      background: #e0e0e0;
    }
  `]
})

3. 條件樣式

@Component({
  styles: [`
    :host(.active) {
      border: 2px solid blue;
    }

    :host([disabled]) {
      opacity: 0.5;
      pointer-events: none;
    }
  `]
})

使用時:

<app-card class="active">突出顯示的卡片</app-card>
<app-card disabled>禁用的卡片</app-card>

4. :host-context 向上查找

@Component({
  styles: [`
    :host-context(.theme-dark) {
      background: #333;
      color: white;
    }
  `]
})

使用時:

<div class="theme-dark">
  <app-card>我會自動使用暗色主題</app-card>
</div>

重要特性

  1. :host 特性:

    • 只影響元件自身的容器元素

    • 不會影響到其他元件

    • 可以和其他選擇器組合使用

  2. :host-context 特性:

    • 可以向上查找整個 DOM 樹

    • 不能向下查找

    • 適合實現主題系統

常見使用場景

1. 製作可重用的 UI 元件

@Component({
  selector: 'app-button',
  template: `<button><ng-content></ng-content></button>`,
  styles: [`
    :host {
      display: inline-block;
    }

    :host(.primary) button {
      background: blue;
      color: white;
    }

    :host(.secondary) button {
      background: gray;
      color: white;
    }
  `]
})

2. 響應式設計

@Component({
  styles: [`
    :host {
      display: block;
      margin: 8px;
    }

    @media (max-width: 768px) {
      :host {
        margin: 4px;
      }
    }
  `]
})

3. 動態狀態管理

@Component({
  styles: [`
    :host {
      display: block;
      transition: all 0.3s ease;
    }

    :host(.expanded) {
      width: 100%;
    }

    :host(.collapsed) {
      width: 50px;
      overflow: hidden;
    }
  `]
})

實戰案例:通用按鈕元件

這是一個結合了 :host 樣式、屬性選擇器和內容投影的完整例子:

1. 元件定義

@Component({
  // 可以同時用於 button 和 a 標籤
  selector: 'button[appButton], a[appButton]',
  templateUrl: './dashboard-button.component.html',
  styleUrl: './dashboard-button.component.css',
})
export class DashboardButtonComponent {}

2. 模板 (dashboard-button.component.html)

<span>
  <ng-content />
</span>
<span class="icon">
  <ng-content select="icon"> → </ng-content>
</span>

3. 樣式 (dashboard-button.component.css)

:host {
  display: inline-block;
  padding: 0.65rem 1.35rem;
  border-radius: 0.25rem;
  font-size: 1rem;
  text-align: center;
  cursor: pointer;
  background-color: #691ebe;
  color: white;
  border: none;
}

:host:hover {
  background-color: #551b98;
}

4. 使用方式

<!-- 按鈕形式 -->
<button appButton>
  Click me
  <span ngProjectAs="icon">⚡</span>
</button>

<!-- 連結形式 -->
<a appButton href="#">
  Visit page
  <span ngProjectAs="icon">→</span>
</a>

重要說明

  1. :host 樣式會直接應用在有 appButton 屬性的元素上

  2. 不需要在元件模板中有 buttona 標籤

  3. 樣式會正確應用,即使元件模板只包含 spanng-content

  4. 可以同時支援按鈕和連結兩種形式

這個例子展示了如何:

  • 使用屬性選擇器創建可重用元件

  • 應用 :host 樣式

  • 結合內容投影

  • 創建靈活的 UI 組件

最佳實踐

  1. 樣式隔離:

    • 使用 :host 確保樣式只影響當前元件

    • 避免使用全域樣式

  2. 主題實現:

    • 使用 :host-context 實現主題系統

    • 配合 CSS 變數使用更靈活

  3. 狀態管理:

    • 使用 class 控制元件狀態

    • 善用偽類處理互動狀態

注意事項

  1. :host 選擇器只能在元件的樣式中使用

  2. :host-context 只能向上查找,不能向下查找

  3. 要小心處理優先級問題

  4. 考慮使用 CSS 變數來提高靈活性

Last updated