ViewEncapsulation.None

什麼是 ViewEncapsulation?

在寫 CSS 時:

  • 通常寫在某個元件的 CSS 只會影響那個元件(這是 Angular 的預設行為)

  • 但有時候你想要 CSS 影響整個網站

這就是 ViewEncapsulation.None 的用途!

預設的樣式封裝

// 預設情況
@Component({
  selector: 'app-my-button',
  template: `
    <button class="my-button">點擊我</button>
  `,
  styles: [`
    .my-button {
      background: blue;
      color: white;
    }
  `]
})

Angular 會自動幫你的樣式加上特殊標記,讓它只影響這個元件:

<!-- 渲染結果會像這樣 -->
<button class="my-button _ngcontent-aaa-1">點擊我</button>

使用 ViewEncapsulation.None

// 使用 ViewEncapsulation.None
@Component({
  selector: 'app-my-button',
  template: `
    <button class="my-button">點擊我</button>
  `,
  styles: [`
    .my-button {
      background: blue;
      color: white;
    }
  `],
  encapsulation: ViewEncapsulation.None  // 關鍵在這裡!
})

這樣設定後:

  • 樣式會變成全域的

  • 會影響整個網站中所有 class="my-button" 的元素

使用時機

1. 做全域主題

@Component({
  selector: 'app-theme',
  template: '',
  styles: [`
    // 這些樣式會影響整個網站
    body {
      font-family: Arial;
    }
    .primary-button {
      background: #007bff;
    }
    .danger-button {
      background: #dc3545;
    }
  `],
  encapsulation: ViewEncapsulation.None
})

2. 修改第三方元件樣式

@Component({
  selector: 'app-custom-datepicker',
  template: `
    <third-party-datepicker></third-party-datepicker>
  `,
  styles: [`
    // 可以覆蓋第三方元件的樣式
    .datepicker-header {
      background: #f0f0f0;
    }
  `],
  encapsulation: ViewEncapsulation.None
})

⚠️ 注意事項

可能遇到的問題

  1. 樣式可能影響到不想影響的元素

  2. 不同元件的樣式可能互相衝突

  3. 很難追蹤樣式來源

使用建議

  1. 命名要小心,避免太常見的 class 名稱

    /* 不好的命名 */
    .button { ... }
    
    /* 好的命名 */
    .app-theme-button { ... }
  2. 盡量用在有明確目的的地方:

    • 網站主題設定

    • 全域共用元件

    • 需要修改第三方元件樣式時

  3. 如果只想修改某個特定元件,最好還是用預設的封裝方式

小技巧

如果你想要某些樣式是全域的,但又不想整個元件都是全域的,可以使用 :host-context:

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

這樣只有當父元素有 .theme-dark 時,樣式才會生效!

Last updated