iT邦幫忙

2022 iThome 鐵人賽

DAY 23
0
Modern Web

前端技能樹的十萬個為什麼系列 第 23

Day 23 - 為什麼要用 Styled-components

  • 分享至 

  • xImage
  •  

前言

今天要來討論比較不一樣的主題,因為還是以 React 生態系為主,經常會用到元件化的開發方式,常常把關注點放在 HTML 與 JS 如何搭配,卻比較少討論到 CSS。

因此,今天讓我們來討論,元件化的 CSS 如何處理吧!

先想一下

  • Styled-components 是在什麼樣的時代誕生的?
  • Styled-components 怎麼解決問題?
  • Styled-components 的優缺點是什麼?
  • Styled-components 適合什麼情境?

Styled-components 是在什麼樣的時代誕生的?

在還沒有使用 React 這樣的前端框架之前,我們會提倡 HTML、CSS、JS 三種檔案分離,透過檔案類型來做關注點分離(SoC),起碼確保不會所有樣式跟程式邏輯都擠在 index.html 裡面。

不過這樣的作法到了 React 這邊來,就顯得有點綁手綁腳,因為 React 使用 JSX,概念上就是把 HTML 寫在 .js 檔案裡面,這是因為 React 的關注點分離,是以「元件」為單位,把一個元件的 HTML、JavaScript 都寫在一個檔案裡面,這樣在做元件化開發的時候會比較方便。

那既然 HTML、JavaScript 都已經放在一起了,CSS 人呢?

如果還是按照傳統的做法,CSS 拉出來獨立的 .css 檔案,然後再透過 index.html 去安插 <link rel="stylesheet" href="main.css" /> 的方式引入進來,這樣很容易會讓各元件的 css 混雜,而且 scope 範圍容易太大,導致不小心有同樣名字的 class 互相覆蓋。

Styled-components 怎麼解決問題?

在這之前,我們要先來了解 CSS-in-JS 是怎麼一回事。

CSS-in-JS

如同上面提到的,為了要以「元件」為開發單位,需要限制 CSS 的作用範圍,以元件為 scope,換句話說就是,要讓每個元件的 CSS 都是獨立的,這樣就可以避免元件之間的 CSS 互相影響覆蓋。

另外,可以讓元件容易維護,也更容易重複使用,因為我可以很清楚知道:

  • 這段 CSS style 只會生效在這個元件內
  • 不用擔心改了會不會影響其他元件
  • 搬動元件時,不用額外搬動 CSS 檔

其中,CSS-in-JS 的應用有像是 css modulesemotionstyled-components,今天就以 styled-components 來討論。

styled-components

styled-components 提供了在 JavaScript 中直接撰寫 CSS 的介面,因為本體是 JavaScript,所以你可以做到:

  • 在 JavaScript 裡面寫 CSS
  • 在 JavaScript 裡面寫的 CSS 裡面寫 JavaScript

比如像官網的例子:

import styled, { css } from 'styled-components';

const Button = styled.button`
  background: transparent;
  border-radius: 3px;
  border: 2px solid palevioletred;
  color: palevioletred;
  margin: 0.5em 1em;
  padding: 0.25em 1em;

  ${props => props.primary && css`
    background: palevioletred;
    color: white;
  `}
`;

const Container = styled.div`
  text-align: center;
`

render(
  <Container>
    <Button>Normal Button</Button>
    <Button primary>Primary Button</Button>
  </Container>
);

上面的 code 跑出來會像這樣:

可以看到 styled-components 的寫法,是使用反引號框起來的,也就是 ES6 的樣板語言語法。框起來的部分雖然看起來像是字串,但實際上會被轉換為可運行的 CSS style,當然也包括了用 ${} 框起來的 JS expression,而這也是 CSS-in-JS 強大的地方,能夠寫一些簡單的判斷邏輯,「在 CSS 裡面寫 JS」。

Styled-components 的優缺點是什麼?

優點

  • 解決 CSS class 命名互相覆蓋的問題
  • 重構與維護 CSS 時,可以專注在元件內的範圍,不用擔心改到其他元件
  • 就近看到每個元件的 CSS,不需要頻繁切換檔案
  • 可以在 CSS 內使用 JavaScript 語法做簡單的判斷

缺點

  • 由於把 CSS 寫在反引號內,語法的 highlight、自動完成、防呆較不完整,需另外裝 plugin 處理
  • CSS 拆散到各元件裡面,較難比對彼此差異,並統一風格

Styled-components 適合什麼情境?

整體來說,CSS-in-JS 的這一類工具的用途算是滿明確的,因為只要是使用元件化開發,關注點分離的方式以「元件」為單位,就需要將 HTML、CSS 寫在 JavaScript 內,更能夠提高可維護性。

結語

心智圖放大版

身為前端工程師,要關心的事情太多,要學的技術太多,有時候 CSS 會覺得「能跑就好」,「看起來差不多就好」,但事實上是,CSS 背後的世界相當廣大,隨著元件化開發的興起,CSS 也要能跟上這個趨勢

其實我算是先跟著專案開始寫 styled-component,才開始理解 CSS-in-JS 背後的概念原因,如果沒有特別去理解的話,其實還真的不知道為什麼要用這個工具呢!

參考資料

styled-components
把 CSS 寫在 JavaScript 中!? - CSS in JS 的使用


上一篇
Day 22 - 為什麼要用 Create-React-App
下一篇
Day 24 - 為什麼要用 Material-ui
系列文
前端技能樹的十萬個為什麼30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
Chiahsuan
iT邦新手 4 級 ‧ 2022-10-14 11:41:32

你好~
針對文章中提到的以下兩點想要請教:

  • styled component 的優點之一是就近看到每個元件的 CSS,不需要頻繁切換檔案
  • 語法的 highlight、自動完成、防呆較不完整,需另外裝 plugin 處理
  1. styled component 的部分在實務上是會和 JSX 放在同一支檔案,還是會另外拆開呢?
    線上課程學到的是會拆成兩支檔案,但從文章敘述和範例程式碼,發覺好像其實可以放在同一支檔案,所以想要請教實務上比較傾向哪種做法
    舉例:Button 元件
    • 做法一: Button.component.jsx + Button.styles.jsx (寫 styled components 在引入到 Button.component.jsx 中)
    • 做法二: Button.component.jsx (裡頭直接寫 styled componet)
  2. 針對 styled component 要有自動完成的功能有建議的 plugin 嗎?

再麻煩你有空幫我解惑~謝謝你!/images/emoticon/emoticon41.gif

ycchiuuuu iT邦新手 4 級 ‧ 2022-10-24 12:50:05 檢舉

你好~

關於第一點,其實我不確定有沒有 best practice 可以效法,所以我提一下自己的考量,如果其他邦友可以幫協助補充就更好了~

我們公司的專案大多會採用你提到的做法二,也就是在 Button.component.jsx 裡頭直接寫 styled-component

原因其實滿單純是因為,我們每個元件都會傾向拆小一點,盡量可以共用,因此一些小的基底元件,可能也就一兩個 styled-component 組成,而大的元件也都是組合那些小元件來的,不太會有 styled-component,就懶得再拆額外一隻檔案來處理了

但我想,如果元件的 UI 邏輯比較複雜,拆出去也會讓程式看起來不會那麼雜,我想這部分的取捨,最好也經過團隊一致共識,比較不會亂。

關於第二點,可以參考這個 VS code plugin

Chiahsuan iT邦新手 4 級 ‧ 2022-10-25 21:39:26 檢舉

感謝你的回覆~ /images/emoticon/emoticon41.gif

我要留言

立即登入留言