React 行內樣式、引入樣式表表、CSS Module、CSS管理進階
目錄:
1. 行內樣式
2. 引入樣式表
3. CSS Module
4. CSS 管理進階
在 React 元素中,使用行內樣式的寫法是這樣的:
行內樣式實際上就是 React 元素上的一個屬性,屬性的值是物件,所有物件的屬性名均為 CSS 屬性。唯一需要注意的是, CSS 屬性寫法遵循小駝峰命名法。
例 子
設定顏色為紅、字型大小為 20 px
import React, { Component } from 'react'; let count = 0; class ListItem extends Component { render() { return (listItem.jsx<div className="row mb-3"> <div className="col-2 themed-grid-col">{this.props.data.id}</div> <div className="col-6 themed-grid-col"> <span style={{ color: 'red', fontSize: 20 }}> {this.props.data.name}</span> </div> <div className={`col-2 themed-grid-col${count ? '' : '-s'}`}> {count} </div> </div> ); } } export default ListItem
頁面表現:
檢視控制檯:
例 子
listItem.css:
在 listItem.css 裡定義一個樣式 title ,這個樣式與上面例子中定義的行內樣式是一樣的。
.title{
color: red;
font-size: 20px;
}
listItem.jsx:
在 listItem.jsx 匯入 listItem.css 來匯入樣式。在 span 元素上設定 className 的值為在 listItem.css 裡定義的 title。
import React, { Component } from 'react'; import './listItem.css'; let count = 0; class ListItem extends Component { render() { return ( <div className="row mb-3"> <div className="col-2 themed-grid-col">{this.props.data.id}</div> <div className="col-6 themed-grid-col"> <span className="title"> {this.props.data.name} </span> </div> <div className={`col-2 themed-grid-col${count ? '' : '-s'}`}> {count} </div> </div> ); } } export default ListItem;listItem.jsx
頁面表現:
檢視控制檯:
用引入樣式表的方式定義CSS樣式時經過打包後樣式是全域性性的
缺點:全域性汙染
例 子
App.js 是 listItem.jsx 的父元件,在 App.js 中也可以使用在 listItem.jsx 中匯入的樣式。
在 App.js 裡新增一個 span 標籤並新增 title 元素,樣式同樣能夠被渲染。
import React, { Component } from 'react'; import ListItem from './components/listItem' const listData = [ { id: 1, name: '紅蘋果', }, { id: 2, name: '青蘋果', }, ] class App extends Component { renderList(){ return listData.map( item => { return <ListItem key={item.id} data={ item }/> }) } render() { return( <div className="container"> <span className="title">Header</span> { listData.length === 0 && <div className="text-center">購物車是空的</div> } { this.renderList() } </div> ) } } export default App;App.js
頁面表現:
說明:
在 React 工程中,最後通過軟體將資源進行打包,引用的 CSS 檔案其實是同一份檔案。檢視當前頁面的原始碼:
搜尋關鍵字,找到樣式 title 所在位置。程式碼顯示,輸出了樣式 title。
檢視控制檯。當整個結構被渲染到頁面上的時候,在 head 標籤裡會生成一個 style 標籤叫 title,所以,在當前頁面只要將標籤的 className 的值為 title ,該標籤都會被渲染成 title 的樣式。
使用 CSS Module 可以解決全域性汙染的問題。
CSS Module 並不是 React 獨有的,它是基於前端工程化開發的一套 CSS 解決方案。
優點:
● 解決了全域性汙染的問題。
● 解決了命名混亂的問題。
● 沒有依賴管理。CSS Module 可以讓整個工程不使用 saas 或者 less 這樣的第三方庫。
listItem.module.css:
.title{
color: 'red';
font-size: 20px;
}
listItem.jsx:
和引入 css 檔案不同的是,不光光要引入檔案,還要從檔案中引入一個物件,這裡命名為 style,有個這個物件之後,就可以通過引用物件屬性的方式去定義樣式。
import React, { Component } from 'react'; import style from './listItem.module.css'; let count = 0; class ListItem extends Component { render() { return ( <div className="row mb-3"> <div className="col-2 themed-grid-col">{this.props.data.id}</div> <div className="col-6 themed-grid-col"> <span className={style.title}> {this.props.data.name} </span> </div> <div className={`col-2 themed-grid-col${count ? '' : '-s'}`}> {count} </div> </div> ); } } export default ListItem;listItem.jsx
頁面表現:
檢視控制檯:
可以看到 class 的值跟程式碼中的 className 的值不一樣,這裡加上了一個隨機字串的字尾,這確保了剛剛定義的 listItem.module.css 的作用域是引入 listItem.module.css 的 listItem.jsx。
使用 CSS Module 依賴
● 不使用選擇器,使用 class 名定義樣式。
● 不層疊 class,使用一個 class 定義樣式
● 用過 compose 來組合
模組的引用分為在同一個檔案裡引用跟不同檔案間引用。
1. 在同一檔案中引用
例 子
listItem.module.css:
common 樣式設定了給文字加下劃線、縮排 2 em。使用 composes 關鍵字可以在 title 樣式裡應用 common 樣式。像上例一樣在 listItem.jsx 中引用 listItem.module.css。
.common{
text-decoration: underline;
text-indent: 2em;
}
.title{
composes: common;
color: red;
font-size: 20px;
}
listItem.module.css
頁面表現:
檢視控制檯:
可以看到在 span 元素上同時有樣式 listItem_title__l6hqj 跟 listItem_common__vea60。
2. 在不同檔案間引用
當整個應用變得越來越複雜的時候,可能需要將獨立的樣式提取出來。
例 子
common.module.css:
存放公用的樣式。
.common{
text-decoration: underline;
text-indent: 2em;
}
common.module.css
listItem.module.css:
引用 common.module.css 中的樣式 common
.title{
composes: common from 'common.module.css';
color: red;
font-size: 20px;
}
listItem.module.css
像上例一樣在 listItem.jsx 中引用 listItem.module.css。
頁面表現:
檢視控制檯:
在實際的 React 開發中,可能上述用法無法滿足需求,下面介紹 2 款更有效地管理 React 中 CSS 的工具:1. Styled-component; 2. Classnames。
Styled-component
Styled-component 是目前較為流行的 CSS In JavaScript 庫,和其它同類型的庫一樣,通過 JS 的賦能解決了原生 CSS 不具備的一些能力。比如說,變數迴圈、函式等等。Styled-component 是一個完整的 CSS 解決方案,有很多比較高階的用法。
Classnames
可以到 npm 詳情頁 www.npmjs.com/package/classnames 進行詳細瞭解。Classnames 就是讓我們更方便地去使用 CSS Module。
好處:可以在同一個標籤上使用更多的 CSS 名稱
安裝 Classnames 工具:
命令:npm install classnames --save
例 1
在上面例子的基礎上,修改 listItem.module.css 跟 listItem.jsx。
listItem.module.css:
新增一個 list-title 樣式,該樣式設定顏色為藍色,渲染到頁面上的話會覆蓋原來的藍色。
listItem.jsx:
引入 classnames。定義 cls 方法,使用 bind 方法,繫結 style 物件,通過 cls 方法在 span 元素上引用樣式 title 跟 list-title。
import React, { Component } from 'react'; import style from './listItem.module.css'; import classnames from 'classnames/bind' const cls = classnames.bind(style); let count = 0; class ListItem extends Component { render() { return ( <div className="row mb-3"> <div className="col-2 themed-grid-col">{this.props.data.id}</div> <div className="col-6 themed-grid-col"> <span className={ cls('title', 'list-title') }> {this.props.data.name} </span> </div> <div className={`col-2 themed-grid-col${count ? '' : '-s'}`}> {count} </div> </div> ); } } export default ListItem;listItem.jsx
頁面表現:
例 2
在上面例 1 的基礎上,修改 listItem.jsx。
listItem.jsx:
引入 classnames 將其命名為 cn。在 render 中定義物件 _cn ,使用 cn 構建一個新的物件,使用 cn 構建一個新的物件,如果 count 不為0,則 themed-grid-col-s 的值為 true。在 span 元素設定 className 的值的時候使用 _cn 。
import React, { Component } from 'react'; import style from './listItem.module.css'; import classnames from 'classnames/bind' import cn from 'classnames' const cls = classnames.bind(style); let count = 0; class ListItem extends Component { render() { const _cn = cn({ 'themed-grid-col-s':!count }) return ( <div className="row mb-3"> <div className="col-2 themed-grid-col">{this.props.data.id}</div> <div className="col-6 themed-grid-col"> <span className={ cls('title', 'list-title') }> {this.props.data.name} </span> </div> <div className={`col-2 themed-grid-col `+_cn}> {count} </div> </div> ); } } export default ListItem;listItem.jsx
頁面表現:
檢視控制檯: