[React 05] styled component


Posted by tzutzu858 on 2021-04-26

React 有很多種方式可以寫 CSS

  1. inline-style,用 style={}
  2. HTML 的 CSS link ,引入外部 CSS
  3. 使用 webpack 打包
  4. styled component 它是一個套件,比較主流用法

官方文件至少 Basics看完,有一些基本用法

安裝

# with npm
npm install --save styled-components

# with yarn
yarn add styled-components

import

import styled from 'styled-components'

舉例 :

const Title = styled.h1` 
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

宣告 Title = styled.h1,h1 就是 h1 標籤,後面用反引號,反引號除了用在樣板字串(template strings)以外,還可以用在標籤模版(tagged template),參考文章 :[筆記] JavaScript ES6 中的模版字符串(template literals)和標籤模版(tagged template)


一樣可以傳 props 進去

例如 tag 裡面加 size = "XL"
接收 props 用 ${},裡面要放 function,通常用箭頭函式比較方便

const TodoButton = styled.div`
    color:rgba(2, 1, 23);
    font-size: ${props => props.size === 'XL' ? '20px' : '12px'}
`

不一定要用三元運算子,可以用短路邏輯

const TodoButton = styled.div`
    color:rgba(2, 1, 23);
    font-size: 12px;
    ${props => props.size === 'XL' && `
    font-size: 20px;
    `}
`

如果是 XL ,那 font-size: 12px; 就會被蓋過去


restyle

對 style component 做 restyle

const RedButton = styled(Button)`
    color: red;
`

如果是對一般的 component 進行 restyle,則需要在 component 傳入 className,用來接收class 屬性

// 繼承 TodoItem component,需要傳入 className
function TodoItem ({ className, size, content }) {
  return (
    <TodoItemWrapper className={className}>
      <TodoContent size={size}>{content}</TodoContent>
      <TodoButtonWrapper>
        <Button>未完成</Button>
        <GreenButton>刪除</GreenButton>
      </TodoButtonWrapper>
    </TodoItemWrapper>
  );
}
  // 繼承 TodoItem
  const BlackTodoItem = styled(TodoItem)`
    background: #000;
  `

function App() {
  const titleSize = "M"
  return (
    <div className="App">
      <TodoItem content={123} />
      <BlackTodoItem content={456} size="XL" />
    </div>
  );
}

@media

透過 Media Query 實作 RWD

const Button = styled.button`
  font-size: 20px;

  @media screen and (min-width: 768px) {
      font-size 16px;
  }

像 Media Query 重複率很高,所以可以額外開個資料夾像是 constants\style.js 檔案,以便重複使用

export const MEDIA_QUERY_MD = '@media screen and {min-width: 768px}'
export const MEDIA_QUERY_LG = '@media screen and {min-width: 1080px}'

便可以在其他檔案引入使用

import { MEDIA_QUERY_MD, MEDIA_QUERY_LG} from './constants/style';

const Button = styled.button`
  font-size: 20px;

  ${MEDIA_QUERY_MD} {
    font-size 16px;
  }

  ${MEDIA_QUERY_LG} {
    font-size: 12px;
  }
`

向量變數

Advanced Usage裡面有個Theming,可以傳個 Global 變數,使用向量變數

index.js 引入 ThemeProvider

import { ThemeProvider } from 'styled-components';

// 提供 theme 的參數
const theme = {
  colors: {
    primary_300: '#ff7777',
    primary_400: '#e33e3e',
    primary_500: '#af0505',
  }
}

ReactDOM.render(
  <ThemeProvider theme={theme}>
    <App />
  </ThemeProvider>,
  document.getElementById('root')
);

App.js 中取用這些變數

const TodoContent = styled.div`
  font-size: 20px;
  color: ${props => props.theme.colors.primary_300};

  ${MEDIA_QUERY_MD} {
    font-size: 16px;
    color: ${props => props.theme.colors.primary_400};
  }

  ${MEDIA_QUERY_LG} {
    font-size: 12px;
    color: ${props => props.theme.colors.primary_500};
  }
`


component 越來越大可以獨立出去

export default function TodoItem() {...}

引入

import TodoItem from './TodoItem'









Related Posts

MTR04_0927

MTR04_0927

同步 & 非同步(4) - async & await

同步 & 非同步(4) - async & await

How to compare a fixed date stored in an object with the current date in JavaScript?

How to compare a fixed date stored in an object with the current date in JavaScript?


Comments