題外話

看到一段我很認同的話:

應該由「新手」來教「超級新手」,為什麼?因為那些新手可能一個禮拜前跟你一樣卡在迴圈,不知道迴圈到底可以做什麼,但是這禮拜他就領悟了。我覺得這時候是最適合教學的時機,因為他們還記得「當初卡住的那種心情」,他們是最懂你心情的人。
By 一個資淺工程師年末的自我省視

剛進公司時,我也是完全沒接觸過 Angular 2,那種徬徨不安的日子依稀猶存,一段日子過去透過不斷查文獻和實作,也終於算是有點懂了,我一直認為程式最困難的地方就是剛入門的門檻,之後儘管也不會就都很簡單,但至少可以暢行無阻。

前言

Angular 2 是一個由組件構成的架構,意思就是所有 UI 都是建立在組件裡面。因此由組件建立風格 (style) 會讓我們使用 Angular 更快樂。我們接著就要談談不同的建立風格技巧,但首先我們要知道 Shadow DOM 和 View Encapsulation。

解釋

Shadow DOM 是 W3C 定義的網頁組件標準之一。它可以讓一群 DOM 實體被藏在單一元素 ( element ) 上 ( 也就是組件的概念 ),而且可以將元素封裝 ( encapsulate ) 風格。意味著被封裝的風格只會被這一群 DOM 使用而已。

但是 Shadow DOM 並不是所有瀏覽器都支援,決定要不要使用以及如何使用 Shadow DOM 的方法就稱為 View Encapsulation,分別有三種狀態:

  • None:無 Shadow DOM 存在。
  • 仿真 (Emulated):試圖模仿出 Shadow DOM,雖然不是真的,至少讓瀏覽器能使用我們的程式碼。
  • 自然 (Native):瀏覽器能完全使用 Shadow DOM。

詳細解釋這三種差在哪裡,可以參考這一篇

設置 encapsulation 大概就長這樣,他會在 @Component 裡面

@Component({
  templateUrl: 'card.html',
  styles: [`
    .card {
      height: 70px;
      width: 100px;
    }
  `],
  encapsulation: ViewEncapsulation.Native
  // encapsulation: ViewEncapsulation.None
  // encapsulation: ViewEncapsulation.Emulated is default 
})

正題開始

接著就來看看有那些技巧可以幫組件加上 CSS

寫在 Component 裡面

這是最常見的方法,也是最推薦的,常常會看到文件都是這樣用。
在我們的 @Component 中實體化:

@Component({
  templateUrl: 'card.html',
  styles: [`
    .card {
      height: 70px;
      width: 100px;
    }
  `],
})

如果使用 view encapsulation 技術的預期結果:

  • None: style 直接被包裝到 <head><style> 裡面
  • Emulated: style 被包裝到 <head><style> 裡面,但可以辨識要對應的 Component
  • Native: 如同預期一般為網頁組件。

.CSS

@ComponentstyleUrls 可以引入對應的 CSS 檔

@Component({
  styleUrls: ['css/style.css'],
  templateUrl: 'card.html',
})

如果使用 view encapsulation 技術的預期結果:

  • None: style 直接被包裝到 <head><style> 裡面。他會被產生於執行完「寫在 Component 裡面」的方式之後。
  • Emulated: style 被包裝到 <head><style> 裡面,但可以辨識要對應的 Component。反而不是引入 link 喔!
  • Native: 如同預期一般為網頁組件。

模板

也可以寫在模板裡面,可以是放在 <style> 標籤或是放在 HTML tag 裡面

//方法一
template: `
    <style>
        h1 {
          color: purple;
        }
    </style>
    <h1>Styling Angular Components</h1>
    `
})
//方法二
@Component({
  template: '<h1 style="color:pink">Styling Angular Components</h1>'
})

如果使用 view encapsulation 技術的預期結果:

  • None:
    • 方法一:style 直接被包裝到 <head><style> 裡面。他會被產生於執行完「寫在 Component 裡面」的方式之後。
    • 方法二:直接寫在 tag 裡面了。
  • Emulated:
    • 方法一: style 被包裝到 <head><style> 裡面,但可以辨識要對應的 Component。
    • 方法二:一樣是直接寫在 tag 裡面了。
  • Native: 如同預期一般為網頁組件。

優先順序

有了這三種加入 CSS 的方法,那麼一次都用上去會怎樣呢?

@Component({
	selector: 'my-app',
//Component style
styles: [`
h1 {
  color: red;
}
`],

//External style
styleUrls[&apos;style.css&apos;],

// Template inline style
template: `
&lt;style&gt;
h1 {
  color: purple;
}
&lt;/style&gt;
&lt;h1 style=&quot;color:green&quot;&gt;Styling Angular Components&lt;/h1&gt;
`

})

分別是:

  • Component style: 字變紅
  • External style: 字變藍
  • Template inline style: 字變紫

點開 Plunker看看答案吧! XD