《深入react技術棧》之樣式處理

RobinsonZhang發表於2019-03-24

基本樣式設定

畫素單位處理

對於樣式中的與大小相關的值,react進行了優化處理,我們直接使用數字即可,不用寫px單位。

let style = {
	width: 18
}
複製程式碼

classname庫

在我們不使用庫之前,需要自己動態拼接classname的字串。原始檔也非常簡單,其下載量也說明其使用頻率比較高,參考原始碼:連結

render(){
	const {isPressed, isActive} = this.state;
	let btnClass = 'btn';
  if(isPressed){btnClass +='pressed' };
  if(isActive){btnClass +='active' };
 
} 

// 有了之後 
import classNames from 'classNames';
render(){
	const {isPressed, isActive} = this.state;
	let btnClass = {
  	'btn':true,
    'pressed':isPressed,
    'isActive':isActive
  }
} 

複製程式碼

基本api如下:

classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'
// 陣列的支援
var arr = ['b', { c: true, d: false }];
classNames('a', arr); // => 'a b c'
複製程式碼

css modules

可以採取的方案

css模組化的方案主要有兩種,分別為行內樣式以及結合js收集依賴進行管理的css modules。

而行內樣式具有明顯的幾個痛點是不能解決的,比如偽元素、動畫、媒體查詢等,所以實際開發中,我們只有一些簡單的樣式處理才會使用行內樣式,整體的樣式方案並不會使用行內樣式。

結合js收集css依賴,可以很方便的進行管理,而且webpack內建的css-loader可以很好地將樣式以及js拆分出來。

面臨的主要問題

全域性樣式汙染

我們預設的樣式選擇器是基於全域性的,會造成全域性樣式汙染,為了覆蓋樣式,我們就需要使用!important這樣的語句來覆蓋。當然我們也可以使用元件內樣式,但這樣會導致外部無法重寫樣式,損失了靈活性。

命令混亂

也是由於全域性命名的規則,由於各個成員的命名規則不統一,導致樣式名稱混亂。

依賴管理不徹底

大多數開發者對於依賴管理不夠徹底,只是關心全域性樣式是否可用,不可用則直接重寫或者覆蓋。

無法共享變數

不同的樣式檔案中,無法共享一些變數。

程式碼壓縮不徹底

使用css-module

開啟模組化

在webpack.config.js中設定css?modules&localIdentName=[name]_[local]-[hash-base64-5].加上之後,我們在引入樣式時就可以實現樣式的重新命名,也可以方便的引入和控制某部分樣式。比如:

// button.css
.normal{}
.disabled{}
複製程式碼
import styles from './button.css';

render(){
	return <button className={styles.normal}/>
}

// 最終生成的css名稱 ,button-normal-abc456
複製程式碼

通過這樣的模組化,解決的問題:

  • 樣式名衝突或者樣式名的全域性汙染
  • 方便自定義樣式名規則,可以簡化樣式名
  • 只需要關心js,引入了js元件便引入了js以及樣式
  • 不需要學習額外的css規則

預設區域性樣式

在上面開啟模組化之後,預設是區域性樣式,也就是加了:local的,如果你希望定義的樣式是全域性樣式,你需要手動的加:global

組合樣式 compose(不建議)

你可以使用compose來組合也就是複用樣式。當然如果你使用的是其他樣式前處理器,其本身具有很靈活的各種樣式處理規則,可以忽略這點,另外一半樣式前處理器也沒有這條語法,請不要使用。

// button.css
.base{}
.active{
	compose:base;
  
}
複製程式碼

樣式命名規則基於BEM

結合react

  • 如果你不想每次都加styles.,可以使用react-css-modules,它使用高階元件的方式避免重複輸入styles
  • 使用模組化時,如果你想使用全域性的這個樣式,可以不用樣式里加,直接在使用的時候加global-css即可,如果是區域性樣式,使用local-module.
  • react使用className的方式與傳統方式的區別是,直接操作樣式還是間接通過操作classname來操作樣式。實際上,在資深的css開發者都會認為,為了樣式更好的維護,我們是建議直接操作樣式的,而不建議在js裡拼接維護較多的樣式程式碼。

小結

本文主要想提醒給大家的幾個點:

  • 與大小有關係的樣式屬性不用加單位
  • 更建議直接通過classname去實現操作樣式,通過物件的方式去配置,而不是自己拼接或者使用原始的classlist去操作
  • 如果你的專案存在較多的樣式汙染或者管理樣式依賴的問題,那麼建議你可以看下css module,也許能解決你的問題,使用也只是配置的問題,不需要額外的其他學習

相關文章