組件的樣式
一、簡單使用
我們可以爲每個組件單獨創建一個css樣式文件,然後在js文件中,直接導入使用:
// header-nav.js
...
import './header-nav.css'
...
但是這種方式導入的樣式會作用於全局。如果要讓當前樣式只生效於當前組件,可以在選擇器上加以限制。比如在聲明組件時爲當前組件的根元素添加一個唯一的id或類名。然後在樣式列表中加上這個選擇器標識即可:
// header-nav.js
...
class HeaderNav extends React.Component {
render() {
return (
<div className="header-nav">
<div></div>
<div></div>
</div>
);
}
}
...
/* header-nav.css */
.header-nav div {
// style list
}
二、React的styled-components
React 是組件結構,建議把 HTML、CSS、JavaScript 寫在一起,以此形成組件低耦合、高複用的特點。所以在React中,組件的結構、樣式和邏輯可能都要使用JS(TS)完成。
React中,用 JS 編寫組件的樣式,要用CSS in JS(文末有具體介紹的文檔鏈接),CSS in JS的庫有很多中,本文介紹styled-components(較爲主流的CSS in JS庫)。
- 安裝styled-components
npm install --save styled-components
我安裝完之後項目無法啓動了,報的錯是,是因爲安裝了新的依賴
react-scripts: command not found
重新安裝了一下node_modules文件夾就好了
npm i
- 全局的樣式
styled-componentsV4之前的版本使用injectGlobal創建全局的樣式。V4將injectGlobal移除了,要創建全局的樣式需要使用createGlobalStyle,並在組件中以子組件的形式調用。
全局的樣式封裝
// src/style.js
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
body {
color: #333;
font-size: 16px;
padding: 30px;
}
`;
export default GlobalStyle
全局的樣式調用
// App.js
...
import GlobalStyle from './style'
...
class App extends Component {
render() {
return (
<div className="App">
<GlobalStyle />
</div>
);
}
}
...
注:一般情況下我們都利用createGlobalStyle做整個項目的樣式重置(reset)。
- 樣式化的組件
通過上面的全局樣式示範,我們能看到,styled-components刪除了組件和樣式之間的映射。當定義樣式時實際上是在創建一個普通的React組件,只不過其中附加了樣式。
樣式化組件的封裝
// src/components/header-nav/style.js
import styled from 'styled-components'
export const Title = styled.div`
font-size: 1.5rem;
color: palevioletred;
`;
樣式化組件的調用
// src/components/header-nav/header-nav.js
import React from 'react'
import { Title } from './style'
class HeaderNav extends React.Component{
render() {
return (
<div className="header-nav">
<div className="box1">你凝視着深淵,深淵也凝視着你。</div>
<Title>
<div className="box2">我的眼睛注視着萬物。</div>
</Title>
</div>
);
}
}
export default HeaderNav
在瀏覽器中的具體呈現效果:
經過解析的DOM結構:
注:
- 在封裝樣式時,聲明瞭Title組件,是一個div標籤(styled.div,如果聲明時寫了styled.h1,那Title就是h1標籤);
- Title可以被複用(樣式化的組件一旦被聲明,只要導入,就可在任意位置複用);
- Title不僅被解析成了div,還自動被添加了一個選擇器,這個選擇器是styled-components自動添加的,方便代碼複用;
- 樣式化的組件調用時,樣式生效於被調用的局部,非全局。
- 樣式化組件的嵌套
封裝
// src/components/header-nav/style.js
import styled from 'styled-components'
export const Title = styled.div`
font-size: 1.5rem;
color: palevioletred;
`;
export const Wrapper = styled.div`
font-weight: bolder;
`;
調用
// src/components/header-nav/header-nav.js
import React from 'react'
import { Wrapper,Title } from './style'
class HeaderNav extends React.Component{
render() {
return (
<Wrapper>
<Title>
只有能被明日的我們銘記,今天才有意義。
</Title>
</Wrapper>
);
}
}
export default HeaderNav
注:樣式化組件嵌套時,子組件會繼承父組件的樣式。
- 樣式化組件的參數
一個樣式化組件被封裝,有些樣式可能需要在被調用的時候根據代碼上下文才能確定,所以styled-components允許在封裝樣式組建時傳參。
封裝
// src/components/header-nav/style.js
import styled from 'styled-components'
export const Title = styled.div`
font-size: 1.5rem;
color: ${props => props.type == 'success' ? 'green' :
props.type == 'warning' ? 'orange' : '#444'};
`;
export const Wrapper = styled.div`
font-weight: bolder;
`;
調用
// src/components/header-nav/header-nav.js
import React from 'react'
import { Wrapper,Title } from './style'
class HeaderNav extends React.Component{
render() {
return (
<Wrapper>
<Title type="warning">只有能被明日的我們銘記,今天才有意義。</Title>
<Title type="success">生命無法承載意義,但你的死亡卻可以。</Title>
</Wrapper>
);
}
}
export default HeaderNav
- 樣式化組件中的子選擇器
封裝
// src/components/header-nav/style.js
...
// 封裝Wrapper組件的同時封裝其子選擇器.box的樣式,如果在Wrapp組件中,某個元素的類名爲box,就會自動生效
export const Wrapper = styled.div`
font-weight: bolder;
.box {
background: #eee;
padding: 20px;
}
`;
...
這些示例都是基本操作,實際上styled-components提供了很多樣式編寫方式,具體請查看文檔。