參考資料:https://github.com/sunyardTime/React-Native-CodeStyle
感謝情書哥無私奉獻
##一、程式設計規約 ###(一) 命名規約
【強制】 程式碼中命名均不能以下劃線或美元符號開始,也不能以下劃線或美元符號結束;
`_name / $Object / name_ / name$ / Object$`
【強制】 程式碼中命名嚴禁使用拼音與英文混合的方式,更不允許直接使用中文的方式; 說明:正確的英文拼寫和語法可以讓閱讀者易於理解,避免歧義。注意,即使純拼音命名方式 也要避免採用;
`反例: DaZhePromotion [打折] / getPingfenByName() [評分] / int 某變數 = 3`
【強制】類名使用 UpperCamelCase 風格,必須遵從駝峰形式,第一個字母必須大寫;
LoginPage/MsgPage
【強制】方法名、引數名、成員變數、區域性變數都統一使用 lowerCamelCase風格,必須遵從駝峰形式,第一個字母必須小寫;
localValue / getHttpMessage() / inputUserId
【強制】常量命名全部大寫,單詞間用下劃線隔開,力求語義表達完整清楚,不要嫌名字長;
正例: MAX_STOCK_COUNT 反例: MAX_COUNT
【強制】使用抽象單詞命名類名或者變數時,需加以修飾;
userMsg 等價於 userMessaage, userPic 等價於 userPicture
【強制】中括號是陣列型別的一部分,陣列定義如下:String[] args; 反例:請勿使用String args[]的方式來定義。
【強制】包名統一使用小寫,點分隔符之間有且僅有一個自然語義的英語單詞。包名統一使用單數形式,但是類名如果有複數含義,類名可以使用複數形式;
正例: 應用工具類包名為com.fcs.open.util、類名為UrlUtils
【強制】資料夾命名統一小寫; 元件,或者類名,首字母全部大寫,遵守駝峰命名法;
img 存放圖片 app APP一些component artcomponent 一些art元件
###(二) 常量定義
- 【強制】不允許出現任何魔法值(即未經定義的常量)直接出現在程式碼中;
- 【推薦】不要使用一個常量類維護所有常量,應該按常量功能進行歸類,分開維護。 如:快取相關的常量放在類:CacheConsts下; 系統配置相關的常量放在類:ConfigConsts下; 說明:大而全的常量類,非得使用查詢功能才能定位到修改的常量,不利於理解和維護;
###(三) 格式規約
- 【強制】大括號的使用約定。如果是大括號內為空,則簡潔地寫成{}即可,不需要換行;如果 是非空程式碼塊則:
- 左大括號前不換行;
- 左大括號後換行;
- 右大括號前換行;
- 右大括號後還有else等程式碼則不換行‘;’表示終止右大括號後必須換行。
- 【強制】 左括號和後一個字元之間不出現空格;同樣,右括號和前一個字元之間也不出現空格;
- 【強制】if/for/while/switch/do 等保留字與左右括號之間都必須加空格;
- 【強制】任何運算子左右必須加一個空格; 說明:運算子包括賦值運算子=、邏輯運算子&&、加減乘除符號、三目執行符等;
- 【強制】縮排採用 4 個空格,禁止使用 tab 字元;
- 【強制】單行字元數限制不超過120個,超出需要換行,換行時遵循如下原則:
第二行相對第一行縮排4個空格,從第三行開始,不再繼續縮排,參考示例;
運算子與下文一起換行;
方法呼叫的點符號與下文一起換行;
在多個引數超長,逗號後進行換行;
const path = Path() .moveTo(0, -radius/2) .arc(0, radius, 1) .arc(0, -radius, 1) .close();
【強制】方法引數在定義和傳入時,多個引數逗號後邊必須加空格;
onMsgByCallAndMsg=(msg, title, type)=>{ this.setState({ callMsgAndMsg:msg }) }
【推薦】方法體內的執行語句組、變數的定義語句組、不同的業務邏輯之間或者不同的語義之間插入一個空行。相同業務邏輯和語義之間不需要插入空行。 說明:沒有必要插入多行空格進行隔開。
【推薦】使用webStomr時,匯入附件的hoop-settings-1.0.jar檔案,可統一格式化。
###(四) package.json
【強制】在使用npm或者yarn獲取資源時,必須在命令末尾新增--save; 說明:使用此命令會把使用的第三方相關資訊寫入到package.json,這樣,其他成員在下載或者更新程式碼後使用npm i,就可以下載最新的npm,若不加 —save ,執行npm i的時候不會下載,其他成員執行專案後在執行可能會報錯,此時需要分析檢視報錯資訊進行重新的npm install XX;
【推薦】使用git或者svn進行程式碼版本管理時,儘量不上傳node_module檔案; 說明:使用package.json進行包管理,下載或更新程式碼後,只需要執行npm i;當有修改npm包,建議進行版本管理,上傳到私有的github倉庫。
【強制】使用第三方或拉取新倉庫時,第一步使用npm i或者npm install; 說明:檢查版本是否存在衝突
【推薦】在使用npm或者yarn獲取資源時,推薦不在命令後新增 -g; 說明,此命令可以讓此資源包在根目錄進行獲取,不利於資源管理;
【強制】當升級或降級react-native版本時,必須進行程式碼備份; 說明:升級失敗或者涉及到原生程式碼時,可以進行程式碼回滾
【強制】每個專案必須配置一個readMe檔案,內容包括測試,正式環境等相關配置檔案以及注意事項;
【推薦】安裝npm包是,推薦~來標記版本號; 說明:~和^的作用和區別:
會匹配最近的小版本依賴包,比如1.2.3會匹配所有1.2.x版本,但是不包括1.3.0 ^會匹配最新的大版本依賴包,比如^1.2.3會匹配所有1.x.x的包,包括1.3.0,但是不包括2.0.0。那麼該如何選擇呢?當然你可以指定特定的版本號,直接寫1.2.3,前面什麼字首都沒有,這樣固然沒問題,但是如果依賴包釋出新版本修復了一些小bug,那麼需要手動修改package.json檔案;和^則可以解決這個問題。但是需要注意^版本更新可能比較大,會造成專案程式碼錯誤,舊版本可能和新版本存在部分程式碼不相容。所以推薦使用來標記版本號,這樣可以保證專案不會出現大的問題,也能保證包中的小bug可以得到修復。###(五) 控制語句
【強制】在一個 switch 塊內,每個case要麼通過 break/return 等來終止,要麼註釋說明程式將繼續執行到哪一個 case 為止;在一個 switch 塊內,都必須包含一個default 語句並且 放在最後,即使它什麼程式碼也沒有。
【強制】在 if/else/for/while/do 語句中必須使用大括號,即使只有一行程式碼,避免使用 下面的形式:
if (condition) statements;
【推薦】推薦儘量少用 else, if-else 的方式可以改寫成:
if(condition){ ... return obj; }
// 接著寫 else 的業務邏輯程式碼; 說明:如果非得使用
if() ... else if( )...else...
方式表達邏輯,【強制】請勿超過3層, 超過請使用狀態設計模式。 正例:邏輯上超過 3 層的 if-else 程式碼可以使用衛語句,或者狀態模式來實現。
4.【推薦】使用三目運算,替換if else結構,精簡程式碼
let account=5; if(account>10){ console.log("true"); }else { console.log("false"); } let msg=account>10?"true":"false";
5.【推薦】除常用方法(如 getXxx/isXxx)等外,不要在條件判斷中執行其它複雜的語句,將復 雜邏輯判斷的結果賦值給一個有意義的布林變數名,以提高可讀性。 說明:很多 if 語句內的邏輯相當複雜,閱讀者需要分析條件表示式的最終結果,才能明確什麼 樣的條件執行什麼樣的語句,那麼,如果閱讀者分析邏輯表示式錯誤呢?
//虛擬碼如下 boolean existed = (file.open(fileName, "w") != null)&& (...) || (...); if (existed) { ... }
###(六) 註釋規約
【強制】類、類屬性、類方法的註釋必須使用 Javadoc 規範,使用/*內容/格式,不得使用 //xxx 方式; 說明:在 IDE 編輯視窗中,Javadoc 方式會提示相關注釋,生成 Javadoc 可以正確輸出相應註釋;在 IDE 中,工程呼叫方法時,不進入方法即可懸浮提示方法、引數、返回值的意義,提高閱讀效率。
【強制】所有的類都必須新增建立者資訊,以及類的說明;
【強制】方法內部單行註釋,在被註釋語句上方另起一行,使用//註釋; 方法內部多行註釋使用/* */註釋,注意與程式碼對齊。
【強制】所有的常量型別欄位必須要有註釋,說明每個值的用途;
【參考】註釋掉的程式碼儘量要配合說明,而不是簡單的註釋掉。 說明:程式碼被註釋掉有兩種可能性: 1)後續會恢復此段程式碼邏輯。 2)永久不用。前者如果沒有備註資訊,難以知曉註釋動機。後者建議直接刪掉(程式碼倉庫儲存了歷史程式碼)。
【參考】對於註釋的要求: 第一、能夠準確反應設計思想和程式碼邏輯; 第二、能夠描述業務含義,使別的程式設計師能夠迅速瞭解到程式碼背後的資訊。完全沒有註釋的大段程式碼對於閱讀者形同 天書,註釋是給自己看的,即使隔很長時間,也能清晰理解當時的思路;註釋也是給繼任者看的,使其能夠快速接替自己的工作。
【參考】好的命名、程式碼結構是自解釋的,註釋力求精簡準確、表達到位。避免出現註釋的一個極端:過多過濫的註釋,程式碼的邏輯一旦修改,修改註釋是相當大的負擔。
【參考】特殊註釋標記,請註明標記人與標記時間。注意及時處理這些標記,通過標記掃描,經常清理此類標記。
- 待辦事宜(TODO):( 標記人,標記時間,[預計處理時間]) 表示需要實現,但目前還未實現的功能。
- 錯誤,不能工作:(標記人,標記時間,[預計處理時間]) 在註釋中用 FIXME標記某程式碼是錯誤的,而且不能工作,需要及時糾正的情況。
###(七) 日誌管理
【推薦】 程式碼中過多使用console.log()會消耗效能,推薦去除不必要的日誌輸入程式碼;
【強制】 在入口檔案新增以下程式碼; 說明:可以在釋出時遮蔽掉所有的console.*呼叫。React Native中有一個全域性變數__DEV__用於指示當前執行環境是否是開發環境。我們可以據此在正式環境中替換掉系統原先的console實現。
if (!__DEV__) { global.console = { info: () => {}, log: () => {}, warn: () => {}, error: () => {}, }; }
這樣在打包釋出時,所有的控制檯語句就會被自動替換為空函式,而在除錯時它們仍然會被正常呼叫。
###(八) 目錄結構規範
以下目錄結構示例中只展示js與靜態資源,不包含原生程式碼: ├── index.ios.js ├── index.android.js └── js ├── component 可複用的元件(非完整頁面) ├── page 完整頁面 ├── config 配置項(常量、介面地址、路由、多語言化等預置資料) ├── util 工具類(非UI元件) ├── style 全域性樣式 └── image 圖片 在component和page目錄中,可能還有一些內聚度較高的模組再建目錄 page/component ├── HomeView.component.js ├── HomeView.style.js └── MovieView ├── MovieList.component.js ├── MovieList.style.js ├── MovieCell.component.js ├── MovieCell.style.js ├── MovieView.component.js └── MovieView.style.js
##二、頁面編寫規範 ###(一) state,props
【強制】 程式碼中初始化state因在constructor(props)函式中,而且儘量對每個變數進行註釋;
【強制】 程式碼中使用setState時,因注意非同步可能導致的問題,儘量使用回撥函式;
this.setState({ //todo },()=>{ //執行setState後執行此函式 })
【強制】 程式碼中使用props時,需進行propTypes檢測和defaultProps預設值初始化;
static propTypes = { color: PropTypes.string, dotRadius: PropTypes.number, size: PropTypes.number }; static defaultProps = { color: '#1e90ff', dotRadius: 10, size: 40 };
4.【強制】 程式碼中用於頁面展示處理UI的元件,命名以Page結尾,自定義元件命名中必須包含Component; 例子:
LoginPage 登入頁 BtuuonComponent 按鈕元件
5.【強制】程式碼中建立陣列或物件使用以下方式;
const user={ name:'time', sex:'男', age:25, }; const itemArray=['0','1','2',3,{name:'25',age:'男'}];
6.【強制】程式碼中函式繫結this,強制使用箭頭函式; 注:除元件原有方法,其他自定義函式命名時,需使用箭頭函式;
//系統元件生命週期方法 constructor(props){ super(props); }; //自定義方法 goMainPage=()=>{ };
7.【推薦】程式碼中一些網路資料初始化,配置資訊,推薦在此生命週期進行初始化;
componentWillMount
8.【強制】程式碼中使用定時器或者DeviceEventEmitter,必須在元件解除安裝進行銷燬或者清除;
componentDidMount() { //注意addListener的key和emit的key保持一致 this.msgListener = DeviceEventEmitter.addListener('Msg',(listenerMsg) => { this.setState({ listenerMsg:listenerMsg, }) }); } goMainPage=()=>{ this.timer = setTimeout( () => { console.log('把一個定時器的引用掛在this上'); }, 500 ); }; componentWillUnmount() { //此生命週期內,去掉監聽和定時器 this.msgListener&&this.msgListener.remove(); // 如果存在this.timer,則使用clearTimeout清空。 // 如果你使用多個timer,那麼用多個變數,或者用個陣列來儲存引用,然後逐個clear this.timer && clearTimeout(this.timer); }
9.【強制】使用本地圖片資源時,需設定寬高並進行適當適配;
imgHeight=screenHeight, imgWidth= screenWidth
10.【強制】在React-Native版本小於0.46.0使用本地圖片資源時,當不指定特殊尺寸圖片時,需引入不同尺寸XX.png,XX2@.png,XX3@.png圖片,並在程式碼引用中,使用如下方式:
<Image style={{flex: 1, height: screenHeight, width: screenWidth}} source={require('../XX.png')}>
說明:當使用XX.png時,程式執行過程中會根據不同螢幕尺寸獲取不同資源;當使用如下方式:
<Image style={{flex: 1, height: screenHeight, width: screenWidth}} source={require('../XX2@.png')}>
時,程式執行過程中不會根據不同螢幕尺寸獲取不同資源。 注意:此方式適用於React-Native0.46.0版本之前。
9.【強制】在React-Native版本大於0.46.0使用本地資源,圖片命名不能出現‘@’符號: 說明:不同大小圖片需要原生不同的尺寸資料夾,系統自動進行不同適配。
###(二) 樣式
【強制】 當元件使用樣式屬性達到三個或者三個以上時,必須使用StyleSheet來建立樣式屬性並進行引用;
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', marginTop:10, }, });
【推薦】 當使用單一屬性,或者全域性樣式屬性時,推薦使用公共樣式類;
//StyleCommon.js module.exports={ topColor:{ backgroundColor: '#3A3D42', }, mainView:{ backgroundColor: '#12141B', }, }
【推薦】 當使用多個state或者props值時,推薦使用以下方式;
const {size, dotRadius, color} = this.props; const { maxNumber,minNumber,}=this.state;
說明使用此方式,程式碼結構清晰簡潔,便於維護;
###(三) var,let,const
- 【強制】對所有變數,物件的引用,使用const,不要使用var;
- 【推薦】如果一定需要引用可變動的變數,物件,建議使用let代替var;
###(四) 程式碼間隔
- 【強制】使用ES6編寫程式碼,定義方法時,每個方法結尾使用‘;’進行分隔;
###(五) 其他
【強制】對元件引用,變數引用,需遵從以下方式;
import React, {Component} from 'react'; import{ View, Text, TouchableHighlight, Image, StyleSheet, InteractionManager, } from 'react-native'; //from react,react-native優先; //from npm庫其次; import { connect } from 'react-redux'; //from 專案內元件其次; import LoadingAndTime from '../component/LoadingAndTime'; import { performLoginAction } from '../action/LoginAction' import {encode} from '../common/Base64'; //變數初始化,常量初始化 最後; let screenWidth = Dimensions.get('window').width; let screenHeight = Dimensions.get('window').height; let typeCode = Platform.OS == 'android' ? 'android-phone' : 'ios-phone' let selectColor=Platform.OS=='android'?null:'white'
【推薦】對元件引用,變數初始化等,在整個頁面或元件內未使用,因去除相關程式碼;
##三、編碼約定
###(一)入口檔案
1.【推薦】統一入口檔案為App.js; 說明:在index.android.js和index.ios.js檔案中,統一入口檔案為App.js,且保持所在目錄和index.android.js和index.ios.js同級。
2.【強制】開發中,不要使用任何後端的開發模式來構建APP結構,如使用MVC,MVP,MVVM等開發模式,React-Native推薦元件化,顆粒化,以上設計模式嚴重違背。若使用Redux,Mobx等資料流第三方,可依據第三方結構編寫構建App。
###(二) 模版檔案
1.【推薦】根據附件,配置程式碼編寫模版,推薦使用第二種配置方式,可配置多種模版。
##四、自定義元件 (一) 自定義元件
【強制】元件命名中必須包含Component; 說明:
ButtonComponent.js LabelComponent.js
【強制】元件中定義的state和props必須都要有註釋,依次說明每個值的含義;
【強制】在每個類的頭部註釋中,必須使用/**/說明此元件的基礎使用方式以及特殊使用方法;
(二) 屬性判斷
【強制】程式碼中使用props時,需進行propTypes檢測和defaultProps預設值初始化;
static propTypes = { color: PropTypes.string, dotRadius: PropTypes.number, size: PropTypes.number };
static defaultProps = { color: '#1e90ff', dotRadius: 10, size: 40 };
(三) 效能優化
【強制】無狀態元件需使用PureComponent而不是Component; 說明:無狀態元件是指內部沒有使用state的元件,但是可以使用props來進行某些屬性控制;
export default class LinkButton extends PureComponent { static defaultProps= { msgName:'請輸入此事件函式名!' };
static propTypes={ msgName:PropTypes.string.isRequired, onPressCall:PropTypes.func, }; render() { return ( <View style={styles.container}> <TouchableOpacity onPress={this.onPressCall} > <View> <Text>{this.props.msgName}</Text> </View> </TouchableOpacity> </View> ); } onPressCall=()=>{ if(this.props.onPressCall){ this.props.onPressCall(); } }
}
2.【推薦】使用InteractionManager.runAfterInteractions,在動畫或者某些特定場景中利用InteractionManager來選擇性的渲染新場景所需的最小限度的內容; 使用場景類似於:
class ExpensiveScene extends React.Component { constructor(props, context) { super(props, context); this.state = {renderPlaceholderOnly: true}; } componentDidMount() { InteractionManager.runAfterInteractions(() => { this.setState({renderPlaceholderOnly: false}); }); } render() { if (this.state.renderPlaceholderOnly) { return this._renderPlaceholderView(); } return ( <View> <Text>Your full view goes here</Text> </View> ); } _renderPlaceholderView() { return ( <View> <Text>Loading...</Text> </View> ); } };
說明:更多使用於Navigator的頁面跳轉 3.【推薦】使用新版本元件替換舊辦法元件; 例如:FlatList替換ListView,React Navigation替換Navigator等
4.【推薦】在使用Touchable系列元件時,進行setState或者大量調幀操作,請使用如下方式:
handleOnPress() { this.requestAnimationFrame(() => { //todo }); }
##五、安全規約
【強制】使用者敏感資料禁止直接展示,必須對展示資料脫敏; 說明:檢視個人手機號碼會顯示成:158****9119,隱藏中間 4 位,防止隱私洩露
【強制】請求傳入任何引數必須做有效性驗證;避免過度請求服務,造成伺服器壓力,或者雙向校驗; 如:驗證手機號長度,是否是手機號等;
##六、其他
【推薦】開發工具使用WebStorm,安裝ESLint外掛進行程式碼檢測,程式碼中不要出現使用ESLint檢查出的錯誤; 說明:變數命名規範,使用var或者const錯誤
【推薦】在WebStorm中匯入附件的hoop-settings.jar檔案,進行程式碼格式化,提交的任何程式碼,都需要進行格式化。快捷鍵是option+command+L
React Native中的約束規範
相關文章
- React Native 開發規範React Native
- oracle中的約束Oracle
- react 開發規範React
- 【SQL】15 SQL 約束(Constraints)、NOT NULL 約束、UNIQUE 約束、PRIMARY KEY 約束、FOREIGN KEY 約束、CHECK 約束、DEFAULT約束SQLAINull
- React程式設計規範React程式設計
- CHECK約束中的NULL條件Null
- React Native 中的狀態列React Native
- React/JSX 編碼規範ReactJS
- MySQL 中的約束及相關操作MySql
- Eclipse中引入spring的約束EclipseSpring
- MySQL中的 UNIQUE約束和UNIQUE索引MySql索引
- PHP中的型別約束介紹PHP型別
- 10、Oracle中的約 束constraintOracleAI
- Eclipse中引入MyBatis約束EclipseMyBatis
- laravel中的命名公約規範及relation N+1問題Laravel
- Javaweb-約束-外來鍵約束JavaWeb
- 【譯】React Native中的動畫漸變React Native動畫
- React Native 中的JSX學習React NativeJS
- Java中的命名規範。Java
- Oracle唯一約束中NULL的處理OracleNull
- Oracle定義約束 外來鍵約束Oracle
- [React Native]react-native-scrollabReact Native
- SQL約束SQL
- Oracle約束Oracle
- oracle 約束Oracle
- MySQL 約束MySql
- 03約束
- 綜合約束
- React Native 中 ScrollView 效能探究React NativeView
- (10)邏輯綜合新增約束(環境約束)
- Oracle中的約束簡單入門試驗Oracle
- Oracle外來鍵約束中NULL的處理OracleNull
- 前端開發規範:命名規範、html規範、css規範、js規範前端HTMLCSSJS
- 泛型的約束理解泛型
- REST 的 6 個約束REST
- oracle的延遲約束Oracle
- (譯)React Native 中的導航器怎麼選?React Native
- React Native 使用 react-native-webview 渲染 HTMLReact NativeWebViewHTML