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