Why ?
- CSS-in-JS
- 不需去處理一些 css 相關的 config set up (e.g. webpack)
- Component with styling
- style 與 component 綁在一起, 且可以透過 props 來動態變動 style
- 程式可讀性提昇
- 不用去寫一堆 className 嵌在 component 上
實作原理
語法
運作
- 當建立一個 styled component 時
1 | const Text = styled.div` |
會透過 hash function 先產生一個 componentId
, 來記錄這個 component
- 當
實例化
一個 styled component 時
1 | return <Text> Hello styled component </Text>; |
會透過 componentId + style string (e.g. ‘position: relative;\ncolor: red;’) 作為 hash input, 產生 className
, 且實例化後的 styled component 會自帶這個 className 屬性
- 所有 styled-component 產生出來的 className, 都會 attach 在 html <style> tag 中
1 | <style> |
- 如此一來, styled component 即可對應到他的 style
- 需要注意一下
styled-components generates an actual stylesheet with
classes
, and attaches those classes to the DOM nodes of styled components via theclassName prop
. It injects the generated stylesheet at the end of the head of the documentduring runtime
.
因此當我們在加工自己寫的 component 時, 需要另外補上 className 這個 props
1 | // MyText 夾帶著 styled factory 產生的 hash class 在 className 這個 props 上, 內層的 div 需要綁上這個 className 才會有效果 . |
Usage tips
styled-components’ selector
1 | const Wrapper = styled.div` |
&
: Reference 到自己 (也就等於自己的 class name)${Other styled component}
: Reference 到別的 styled-components (也就等於他人的 class name)- 上述例子中,
只有 1, 3 會有效果
,下面說明 1~4 分別會在 <style> tag 中建立什麼,假設 Text 的 class 為 .123, Wrapper 的 class 為 .456
1 | 1. |
- 結論
- 子無法 Ref 到上層 Component 去設定其 style (見 2.)
- 子無法先 Ref 到上層 Component 去設定其下層的 style (見 4.), 除非其中會 Ref 到該子 (見 3.)
Peformance issue
產生過多的 class in style tag
發生情境
假設有一個 styled component, 其 width 會隨著傳入的 width props 不同而改變
1 | const Row = styled.div` |
而實例化的 Row, 其 width props 會隨著時間動態改變(假設透過 setInterval 一直去改變其 width 之類的), 這樣就會產生無限個
class, attach 在 <style> tag 裡面, 但實際上仍然是同一個元素
, 差別只在 width 不同
無限個
class- 會產生無限個 CSSOM 節點, 對 Memory 是個負擔
Prevent
use the style attr for all dynamic styles with undermined number of results
1 | const Row = styled.div.attrs({ |
上面例子實體化的 styled component DOM 會夾帶 inline style
- width, 當動態去改變 width 時, 會直接去更動 inline style width 的值
, 並不會去產生新的 class 在 style tag 裡 => don’t generate bunch of CSS rules which only differ by one number so CSSOM is smaller and memory consumption drops