聊一聊 React 中的 CSS 樣式方案


和 Angular,Vue 不同,React 並沒有如何在 React 中書寫樣式的官方方案,依靠的是社區眾多的方案。社區中提供的方案有很多,例如 CSS Modules,styled-components,styles jsx 等等。

接下來會詳細地說一下這幾種方案,在說這幾種方案之前,首先說一下 React 官方提供的構建工具 create-react-app 構建的項目中使用 css 的問題。

使用 create-react-app 創建的項目引入 css 文件的問題

使用 create-react-app 構建一個項目之后,會有 index.js,index.css,App.js 等文件,為了說明問題我又新建了一個 App1.js 文件,為了簡便文件內容讓我刪除改動了一些。

index.css

.huisiyuan {
  background: red
}

index.js

import App from './App';
import App1 from './App1';
import './index.css';

ReactDOM.render(
  <React.StrictMode>
    <App />
    <App1 />
  </React.StrictMode>,
  document.getElementById('root')
);

App.js

import React, { Component } from 'react';
class App extends Component {
	render() {
		return <div className='huisiyuan'>組件App</div>
	}
}
export default App;

App1.js

import React, { Component } from 'react';
class App1 extends Component {
	render() {
		return <div className='huisiyuan'>組件App1</div>
	}
}
export default App1;

index.js 中引入的 index.css 在瀏覽器中是出現在 head 標簽下的 style 標簽下,因此任何在 index.js 中使用的組件都可以使用 index.css 中的樣式。

1584845869211

例如想讓組件 App 的背景顏色為紅色,index.css 中正好是這樣設置的,但是 App1 中的背景顏色也會跟着變成紅色。

說明了 creat-react-app 創建項目后直接使用 import 引入 css 文件出現的問題,接下來講一下社區中提供的各種方案。

CSS Modules

CSS Modules 的核心

CSS Modules更詳細的介紹可以參考阮一峰老師 CSS Modules 用法教程

因為CSS的規則都是全局的,任何一個組件的樣式規則,都對整個頁面有效,這可能會導致大量的沖突。例如,如果我有兩個css文件,它們的中的一些樣式名是一樣的,那么就會被覆蓋,簡單的解決辦法就是將樣式的命名變得復雜且不重復,但這樣樣式多了也很難避免重復,且命名變得復雜。

CSS Modules 就解決了這個問題,在一個組件中引入的類經過構建工具編譯之后會變成獨一無二的哈希字符串.

下面是一個 App 組件

import React, { Component } from 'react';
import xxx from 'index.css';

class App extends Component {

	render() {
		return <div className={xxx.huisiyuan}>組件App</div>
	}

}

export default App;

和上面引入 css 文件不同的是,這里將 index.css 文件輸入到 xxx 對象,xxx.huisiyuan 代表一個 class。

.huisiyuan {
  background: red;
}

構建工具會將 xxx.huisiyuan 編譯成一個哈希字符串,同樣 index.css 文件中的 .huisiyuan 也將被編譯成同樣的哈希字符串,這樣這個類名就獨一無二了。

這樣這個類就有了局域的概念,其它組件不引入使用這個 index.css 文件就不會應用到這個類的樣式,因為編譯后的哈希字符串其它組件是不知道的。

一般情況下,

局部樣式文件 全局樣式文件
命名方式 xxx.module.css xxx.css
引入方式 import xxx from './xxx.mouule.css' import './xxx.css'
用法
huisiyuan
huisiyuan

styled-components

styled-components 見名知義就是一個帶樣式的組件。

React 的一個理念就是 all in JS,styled-components 將樣式直接寫入到組件中,得到的是一個樣式的組件,在調用組件時是帶着樣式的。

Styled Component是react的一個第三方庫,是CSS in JS 的優秀實踐和代表,將CSS寫在JS中,可以實現常規CSS所不好處理的邏輯復雜、函數方法、復用、避免干擾。

使用方法:

首先安裝 style-components, npm install style-components --save.

下面的代碼中 Div 就是一個帶樣式的組件(帶樣式的 Div)

import React, { Component } from 'react';
import styled from 'styled-components';

const Div = styled.div`
	color: red;
`;

class App extends Component {

	render() {
		return (
			<div>
				<Div big>hello world</Div>
			</div>
		) 
	}

}

export default App;

右下圖可以看出,styled-components 自動給 div 加了一個 class。

1584863507228

styled-components 還可以獲取到組件的屬性,並且在定義樣式時進行一些邏輯操作。

const Div1 = styled.div`
	color: red;
	${(props)=> props.big&&`
		font-size: 72px
		`}
`;

const Div2 = styled.div`
	color: blue;
	${(props)=> props.small&&`
		font-size: 30px
		`}
`;

class App extends Component {
	render() {
		return (
			<div>
				<Div1 big>hello world</Div1>
				<Div2 small>hello world</Div2>
			</div>
		) 
	}
}

當 Div1 組件中有 big 屬性時會設置 font-size: 72px,結果如下圖。

1584864134816

styled jsx

見名知義就是帶樣式的 JSX,一般有下面三種形式。

1) 行內樣式

行內樣式是一種最基本的寫法,和在HTML中寫的元素內聯樣式差不多,但是設置的樣式是一個對象。

<div style={{color: red, background: blue}}>hello<div/>

為什么要用兩個大括號?

因為在JSX中渲染的JS表達式,它們必須被放在一對大括號里,{style}可以視為一個JS對象。所以第一對大括號正是將JS表達式放入JSX解析,里面的那對大括號則創建了一個style對象實例,所以在這里style是作為一個對象傳入組件 。

2)聲明樣式

聲明樣式其實是行內樣式的一種改進寫法,在render函數外部創建style對象,然后傳遞給組件,讓css與標簽分離 。

const style = {
	color: red,
	background: blue
}

class App extends Components {
	render() {
		return (
			<div style={style}>hello</div>
		)
	}
}

3)引入樣式文件

其實這一種是 CSS Modules 中全局樣式文件的應用,在這里再提一下,用法比較簡單就是將樣式文件通過 import 語句引入進來,問題就是頁面上的所有組件都能應用這個文件中的樣式。

App.css

.huisiyuan {
  color: red;
  background: blue;
}

App.js

import React, { Components } from 'react';
import './App.css';
import  App1 from './App1';

class App extends Components {
	render() {
		return (
      <App1 >
		)
	}
}

APP1.js

import React, { Components } from 'react'; 

class App1 extends Components {
	render() {
		return (
      <div className='huisiyuan'>hello</div>
		)
	}
}

在 App.js 中引入了 App.css 但是在 App1.js 中·並沒有引入,但是在 App1 組件內部依然可以使用 App.css 中的樣式,App1 組件中hello 應用 App.css 中的樣式,如下圖所示。

1584926371574

總結:

上面總結的三種方法,推薦使用 CSS Modules 或者 styled-components,在平時做一些小 demo 的時候可以使用 styled jsx 的方法。

完,如有不恰當之處歡迎指正哦。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM