抉擇系列:在技術開發的過程中我們會面臨著各種各樣的抉擇,我們在不同情境下該如何選擇恰當的技術,這是本系列文章想要解決的問題。
在 React 開發的過程中我們常常會遇到一些抉擇,下面我將選取其中一些個人認為重要的抉擇來一一分析。但請記住以下所說的都只是的建議,可能有一些方面也沒有考慮到,大家還是需要依據實際情況自己選擇最合適的,切勿隨波逐流。
抉擇 1:開發環境搭建
當開始React開發之前,你或你的團隊必須先考慮選擇什麼樣的開發環境,先愉快的呈上群眾的選擇圖。
![React 開發中面臨的九個重要抉擇](https://i.iter01.com/images/6f35bfe56b585979251f0ab7a8f68b388dc2bd166cfa42da0cb09e502f5bbf68.png)
通用場景建議使用 create-react-app,它將滿足你大部分的開發需求。如果預設配置不能滿足你的需求,執行 npm run eject
按需修改你的配置吧(溫馨提示:此過程式不可回退的)。
其他可替代
如果以上皆不能滿足你的需求時,親,自己動手,豐衣足食。
抉擇 2:型別
JavaScript 是弱型別語言,你可能忽視型別檢查,也可能需要引入型別檢查。下圖是群眾的選擇圖,你將如何選擇?
![Types](https://i.iter01.com/images/85ded9c7d12b9bd749f4e875bbc23460cbde17382b33d77534429ed49f087100.png)
如果你懶得折騰,那 prop-types 可以滿足你的型別驗證,也會避免大部分的型別問題。
如果你喜歡折騰,追求完美,沒有問題還有下面兩種選擇:
-
TypeScript JavaScript 的超集,最終可編譯成清晰與整潔的原生JavaScript程式碼.
-
Flow 為 Javascript 新增靜態型別檢查,用於提高開發者的效率與程式碼質量。
抉擇 3:ES5(createClass) VS ES6(class)
如果你開發環境使用的是ES5語法,那你沒得選擇只能使用createCalss,推薦官方文章《非ES6環境下如何使用React》
如果你開發環境使用ES6語法,強烈建議使用 class,使用起來更簡單,Facebook 也推薦使用 Class,示例程式碼如下:
class SayHello extends React.Component {
constructor(props) {
super(props);
this.state = {message: 'Hello!'};
}
render() {
return (
<p>
Say: {this.state.message}
</p>
);
}
}
複製程式碼
抉擇 4:類 VS 純函式
如果你不需要使用生命週期,儘可能使用無狀態純函式(Stateless functional components:react-v0.14版本新增的新特性)。
無狀態純函式簡單例子:
// 無狀態純函式元件,使用 ES5
var Aquarium = function(props) {
var fish = getFish(props.species);
return <Tank>{fish}</Tank>;
};
// 無狀態純函式元件,使用 ES2015 (ES6) 箭頭函式:
var Aquarium = (props) => {
var fish = getFish(props.species);
return <Tank>{fish}</Tank>;
};
// 或者再使用物件解構與預設的返回,簡單:
var Aquarium = ({species}) => (
<Tank>
{getFish(species)}
</Tank>
);
// 然後使用: <Aquarium species="rainbowfish" />
複製程式碼
依據單一職責原則,你的元件應該只有且只一個職責,內部的邏輯儘量設計扁平。如果邏輯複雜,那你要問自己元件是否還需要分解,使用純函式會使你時時刻刻考慮元件的設計是否合理。
總之一句話,純函式能幫你更好的設計的你元件,底層的原子元件儘量使用純函式,可複用或者更復雜的邏輯可以考慮抽離出高價邏輯元件。
也並不是說所有地方都要使用純函式,如果你的元件確實需要狀態與生命週期相關操作,那就使用類。
附帶兩篇同一個作者的不同觀點的文章(英文):
- 使用無狀態函式元件的9個理由 React Stateless Functional Components: Nine Wins You Might Have Overlooked
- 7個不使用無狀態純函式元件的理由 7 Reasons to Outlaw React’s Functional Components
抉擇 5:State
接下來你要考慮的是如何管理你的狀態資料,業界已經有很多方案,群眾的選擇是
![React 開發中面臨的九個重要抉擇](https://i.iter01.com/images/249b3aee7092f3a75a980e073bf762c30e01fe425ab214f3c31162cc8b5135c3.png)
如果是簡單WEB的應用,可能 React 提供的 setState() 就完全能滿足你的需求,夠用就好彆強行加入其它 State 管理框架。
如果是大型的WEB應用,個人建議使用 Redux。Redux是JavaScript應用程式的可預測狀態管理容器。它可以幫助您編寫行為一致的應用程式,可在不同環境(WEB客戶端,伺服器和手機應用等)中執行,並且易於測試。
順便提一下Redux借鑑的其核心思想之一的框架 Flux,有興趣可以是研究一下。
Bobx,簡單,可擴充套件的狀態管理庫。本人也沒有使用就不細說了
抉擇 6:繫結(Binding)
一張圖能搞定,就不多做解釋了
![React 開發中面臨的九個重要抉擇](https://i.iter01.com/images/fd1b647ca896a69e075f4bb19434e8f8846a0f5bd1b16e824db2ab805f7a047f.jpg)
使用箭頭函式繫結示例程式碼如下:
class SayHello extends React.Component {
constructor(props) {
super(props);
this.state = {message: 'Hello!'};
}
// 使用箭頭函式banding
handleClick = () => {
alert(this.state.message);
}
render() {
return (
<button onClick={this.handleClick}>
Say hello
</button>
);
}
}
複製程式碼
使用建構函式中繫結示例程式碼如下:
class SayHello extends React.Component {
constructor(props) {
super(props);
this.state = {message: 'Hello!'};
// 在用建構函式banding
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
alert(this.state.message);
}
render() {
return (
<button onClick={this.handleClick}>
Say hello
</button>
);
}
}
複製程式碼
抉擇 7:樣式(Styling)
樣式的選擇太多了,我們就不一一列舉,我們選擇幾個React開發者常用的選擇項,群眾的選擇盡在下圖中
![React 開發中面臨的九個重要抉擇](https://i.iter01.com/images/76d33be35a94439136b4b52a4b5d3d65576be1151f90bc4f3a3e54880fd7a703.png)
依據群眾的選擇,好像(由於上圖群眾的人數不詳,樣本不能足,只能說好像) CSS-in-JS 正在吞噬 CSS-Modules 的份額。
Cory House 的選擇編寫程式碼使用SASS,命名使用BEM已經足夠,他也關注 styled-components。
本人傾向邏輯,結構與樣式分離,現階段還是使用SASS,命名使用BEM。近期在探討更適合自己的樣式CSS組織架與命名方式,後續會有專門的文章(《CSS架構解決方案系列》),本文就不做深入研究了。
下面簡單的羅列一下,如何更好的組織樣式的解決方案: OOCSS, SMACSS, BEM, ITCSS, ECSS, SUIT CSS, Atomic Design, Atomic。歡迎補充!
抉擇 8:複用邏輯
接下來你要面對的是如何複用你的邏輯,程式設計世界的一句名言“不要重複自己”。默默的看著群眾的選擇圖
![React 開發中面臨的九個重要抉擇](https://i.iter01.com/images/13c6de309c3ca1e9d2594a946b49dfd5af21e0d78354578a86454020ce626c84.png)
React 最初是使用Mixins,但是使用 mixins會導致一些BUG與被認為是有害的(Mixins Considered Harmful)。
高階元件(Heigher Order Components), 如果不瞭解可以閱讀下列文章:
- Facebook官方文件英文 Higher-Order Components
- 中文閱讀 深入理解 React 高階元件
高階元件時現在最流行的方案,但還是需要了解 render props,它比高階元件跟容易閱讀與建立。其實我還沒有深入理解與實踐 render props,無法給出建議,看你自己的選擇。
我現在使用的是高階元件,未來也不排除會使用 render props,軟體行業不不變的主題就是“變化”,說不定還會有更合理的方案呢?
抉擇 9:目錄結構
你是喜歡所有元件共用一個資料夾呢,如下
src/
|- App.js
|- RewarmView.js
|- RewarmSearchInput.js
|- RewarmImage.js
|- RewarmLoading.js
|- RewarmError.js
|- giphyLoadData.js
複製程式碼
還是每個元件有自己的資料夾,基本結構如下
src/
|- App.js
|- RewarmSearch/
|- index.js
|- View.js
|- SearchInput.js
|- Image.js
|- Loading.js
|- Error.js
|- loadData.js
複製程式碼
收起資料夾,看起來是不是很整潔
src/
|- App.js
|- RewarmSearch/
複製程式碼
每個元件在其單獨的資料夾,更詳細可閱讀
- Writing Scalable React Apps with the Component Folder Pattern
- The 100% correct way to structure a React app (or why there’s no such thing
個人推薦的是每個元件擁有自己的資料夾,你呢?
說在最後
本人雖然有6年前端的開發經驗,但文章難免會有遺漏,也可能與你的想法是對立的,歡迎大家提出建議或說出你不一樣的觀點。
參考文獻
《 8 key React Component Decisions 》 (本連結需要翻牆)