摘要:本文針對技術棧,總結了一些最佳實踐,對編寫高質量的代碼有一定的參考作用。二最佳實踐說明多用如果組件是純展示型的,不需要維護和生命周期,則優先使用。理解并遵循這些最佳實踐,寫出來的代碼質量會有一定的保證。
歡迎關注我的公眾號睿Talk,獲取我最新的文章:
在日常開發和 Code Review 的時候,常常會發現一些共性的問題,也有很多值得提倡的做法。本文針對 React 技術棧,總結了一些最佳實踐,對編寫高質量的代碼有一定的參考作用。
二、最佳實踐 & 說明多用 Function Component
如果組件是純展示型的,不需要維護 state 和生命周期,則優先使用 Function Component。它有如下好處:
代碼更簡潔,一看就知道是純展示型的,沒有復雜的業務邏輯
更好的復用性。只要傳入相同結構的 props,就能展示相同的界面,不需要考慮副作用。
更小的打包體積,更高的執行效率
一個典型的 Function Component 是下面這個樣子:
function MenuItem({menuId, menuText, onClick, activeId}) { return ({menuText}); };
多用 PureComponent
如果組件需要維護 state 或使用生命周期方法,則優先使用 PureComponent,而不是 Component。Component 的默認行為是不論 state 和 props 是否有變化,都觸發 render。而 PureComponent 會先對 state 和 props 進行淺比較,不同的時候才會 render。請看下面的例子:
class Child extends React.Component { render() { console.log("render Child"); return ({this.props.obj.num}); } } class App extends React.Component { state = { obj: { num: 1 } }; onClick = () => { const {obj} = this.state; this.setState({obj}); } render() { console.log("render Parent"); return (); } }
點擊按鈕后,Parent 和 Child 的 render 都會觸發。如果將 Child 改為 PureComponent,則 Child 的 render 不會觸發,因為 props 還是同一個對象。如果將 Parent 也改為 PureComponent,則 Parent 的 render 也不會觸發了,因為 state 還是同一個對象。
遵循單一職責原則,使用 HOC / 裝飾器 / Render Props 增加職責
比如一個公用的組件,數據來源可能是父組件傳過來,又或者是自己主動通過網絡請求獲取數據。這時候可以先定義一個純展示型的 Function Component,然后再定義一個高階組件去獲取數據:
function Comp() { ... } class HOC extends PureComponent { async componentDidMount() { const data = await fetchData(); this.setState({data}); } render() { return (); } }
組合優于繼承
筆者在真實項目中就試過以繼承的形式寫組件,自己寫得很爽,代碼的復用性也很好,但最大的問題是別人看不懂。我將復用的業務邏輯和 UI 模版都在父類定義好,子類只需要傳入一些參數,然后再覆蓋父類的幾個方法就好(render的時候會用到)。簡化的代碼如下:
class Parent extends PureComponent { componentDidMount() { this.fetchData(this.url); } fetchData(url) { ... } render() { const data = this.calcData(); return ({data} ); } } class Child extends Parent { constructor(props) { super(props); this.url = "http://api"; } calcData() { ... } }這樣的寫法從語言的特性和功能實現來說,沒有任何問題,最大的問題是不符合 React 的組件編寫習慣。父類或者子類肯定有一方是不需要實現 render 方法的,而一般我們看代碼都會優先找 render 方法,找不到就慌了。另外就是搞不清楚哪些方法是父類實現的,哪些方法是子類實現的,如果讓其他人來維護這份代碼,會比較吃力。
繼承會讓代碼難以溯源,定位問題也比較麻煩。所有通過繼承實現的組件都可以改寫為組合的形式。上面的代碼就可以這樣改寫:
class Parent extends PureComponent { componentDidMount() { this.fetchData(this.props.url); } fetchData(url) { ... } render() { const data = this.props.calcData(this.state); return ({data} ); } } class Child extends PureComponent { calcData(state) { ... } render() {} } 這樣的代碼是不是看起來舒服多了?
如果 props 的數據不會改變,就不需要在 state 或者組件實例屬性里拷貝一份
經常會看見這樣的代碼:
componentWillReceiveProps(nextProps) { this.setState({num: nextProps.num}); } render() { return({this.state.num}); }num 在組件中不會做任何的改變,這種情況下直接使用 this.props.num 就可以了。
避免在 render 里面動態創建對象 / 方法,否則會導致子組件每次都 render
render() { const obj = {num: 1} return({...}} /> ); } 在上面代碼中,即使 Child 是 PureComponent,由于 obj 和 onClick 每次 render 都是新的對象,Child 也會跟著 render。
避免在 JSX 中寫復雜的三元表達式,應通過封裝函數或組件實現
render() { const a = 8; return ({ a > 0 ? a < 9 ? ... : ... : ... }); }像上面這種嵌套的三元表達式可讀性非常差,可以寫成下面的形式:
f() { ... } render() { const a = 8; return ({ this.f() }); }多使用解構,如 Function Component 的 props
const MenuItem = ({ menuId, menuText, onClick, activeId, }) => { return ( ... ); };定義組件時,定義 PropTypes 和 defaultProps
例子如下:
class CategorySelector extends PureComponent { ... } CategorySelector.propTypes = { type: PropTypes.string, catList: PropTypes.array.isRequired, default: PropTypes.bool, }; CategorySelector.defaultProps = { default: false, type: undefined, };避免使用無謂的標簽和樣式
下面這種情況一般外層的div是多余的,可以將樣式直接定義在組件內,或者將定制的樣式作為參數傳入。例外:當ServiceItem需要在多個地方使用,而且要疊加很多不一樣的樣式,原寫法會方便些。
// bad三、總結// good本文列舉了筆者在項目實戰和 Code Review 過程中總結的 10 條最佳實踐,當中的一些寫法和原則只代表個人立場。理解并遵循這些最佳實踐,寫出來的代碼質量會有一定的保證。如果你有不同的意見,或者有補充的最佳實踐,歡迎留言交流。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101570.html
相關文章
React 可視化開發工具 shadow-widget 最佳實踐(上)
摘要:上例的功能塊定義了如下節點樹入口節點是面板,結合該節點的函數書寫特點,我們接著介紹最佳實踐如何處理功能塊之內的編程。 本文介紹 React + Shadow Widget 應用于通用 GUI 開發的最佳實踐,只聚焦于典型場景下最優開發方法。分上、下兩篇講解,上篇概述最佳實踐,介紹功能塊劃分。 showImg(https://segmentfault.com/img/bVWu3d?w=6...
TypeScript 3.0 + React + Redux 最佳實踐
摘要:首先聲明這篇文章是想說明一下最新版本的的新特性帶來的極大的開發體驗提升而不是如何利用開發應用這個特性就是對的支持在的中有說明具體可以參考這里在版本之前我們在開發應用尤其是在配合一類庫的時候經常用到諸如之類的封裝而這些函數其實都可以用裝飾器的 首先聲明, 這篇文章是想說明一下最新版本的 TypeScript(3.0) 的新特性帶來的極大的 React 開發體驗提升. 而不是如何利用 Ty...
多React Native項目時依賴管理的最佳實踐
摘要:此時會把當前路徑作為一個本地,在全局路徑下創建一個軟鏈接。所有依賴于全局路徑下的都必須是一個版本的,并沒有提供多版本號依賴的解決方法。因此,還是建議選擇一個常用的版本安裝在全局路徑,個別需求其他版本號的的項目,使用來配置局部依賴。 在實際開發過程中,經常需要同時運行和修改多個React Native工程,比如運行github上的開源項目以觀察某種控件的實際效果。那么此時,各項目下的初始...
React.js 最佳實踐(2016)_鏈接修正版
摘要:譯者按最近依舊如火如荼相信大家都躍躍欲試我們團隊也開始在領域有所嘗試年應該是逐漸走向成熟的一年讓我們一起來看看國外的開發者們都總結了哪些最佳實踐年在全世界都有很多關于新的更新和開發者大會的討論關于去年的重要事件請參考那么年最有趣的問題來了我 譯者按:最近React(web/native)依舊如火如荼,相信大家都躍躍欲試,我們團隊也開始在React領域有所嘗試. 2016年應該是Reac...
發表評論
0條評論
閱讀 1378·2021-09-24 10:26
閱讀 1689·2019-08-30 14:14
閱讀 2099·2019-08-29 16:54
閱讀 363·2019-08-29 14:09
閱讀 1468·2019-08-29 12:55
閱讀 922·2019-08-28 18:13
閱讀 1573·2019-08-26 13:39
閱讀 2560·2019-08-26 11:43