相信好多寫React Native的都是前端出身,固然碰見問題的,也不少時候會想從前端出發,但因爲React Native自己的限制,並非支持足夠多的屬性和樣式,因此Bo主結合本身的開發實踐,並總結了一些未來開發可能會碰見的問題並給出一些小的代碼參考;(PS實現很差的但願能你們提出見解,本身也會更新)。javascript
本身將代碼放到了example
下,而且作成了一個App.這樣能夠查看具體運行效果:html
截圖1:前端
項目地址vue
git clone https://github.com/JackPu/react-native-tips.git
進入example 目錄java
react-native start
用xcode打開ios目錄下的項目,運行就能夠看到上面的運行界面了。react
寫習慣了html咱們看到按鈕,第一時間想到的即是Button,可是目前React Native並無這個組件,不過不要緊,咱們可使用 TouchableHighlight,TouchableOpacity來實現按鈕組件,固然經常使用的樣式能夠應用在上面,造成格式各樣的按鈕。android
<TouchableHighlight onPress={this._onPressButton}> <Text>This is Button</Text> </TouchableHighlight>
若是你實在很是喜歡按鈕的話,不要緊,咱們引入已經封裝好的組件react native button
ios
npm install react-native-button --save
安裝好後,你就能夠大膽的這樣寫了:git
<Button style={[Css.btn,Css.btnP]} styleDisabled={{color: 'red'}} onPress={() => this._handlePress()}> This is a button </Button>
CSS3中你們可能都會用到text-oveflow
,然而RN 的Text並無這個屬性,不過咱們能夠經過設置numberOfLIne 或者JS自動計算來實現:github
<Text numberOfLines={1}>your long text here<Text>
寫樣式的時候有的時候咱們常常會用到百分比,然而React Native並不支持這樣的單位,除了用Flex佈局外,咱們能夠經過另一個方式得到:Dimensions
。固然因爲都是JS
所以咱們能夠取巧,用JS計算下,好比30%,
var React = require('react-native'); var {Dimensions,StyleSheet,Component} = React; // 咱們可使用Dimensions 去獲取窗口寬度 var fullWidth = Dimensions.get('window').width; let thirtyPercentiWidth = fullWidth * 0.3; // Your stylesheet var styles = StyleSheet.create({ .wrap{ width: thirtyPercentiWidth, } });
在App中的經常使用的列表除了水平列表外,咱們還須要柵格化的列表。好比相似於下面這樣:
作出相似的界面其實只要限制住你每個小方塊的寬度就好了。
var styles = StyleSheet.create({ list: { justifyContent: 'flex-start', flexDirection: 'row', flexWrap: 'wrap' }, row: { justifyContent: 'center', padding: 5, margin: 5, width: (Dimensions.get('window').width - 30) / 3, height: 100, backgroundColor: '#fff', alignItems: 'center', }, thumb: { width: 55, height: 55 }, text: { flex: 1, marginTop: 10, } }); // render row <TouchableHighlight onPress={() => this._pressRow(rowID,rowData)} underlayColor='rgba(0,0,0,0)'> <View> <View style={styles.row}> <Image style={styles.thumb} source={{uri: rowData['game_icon']}} /> <Text numberOfLines={1} style={styles.text}> {rowData['game_name']} </Text> </View> </View> </TouchableHighlight>
不管何時,做爲一個前端er,在遇到比較棘手的問題時候,咱們均可以回到原點,用一個網頁去解決。所以不管如何都須要學會使用React Native webview。除此以外,部分頁面,其實徹底能夠由網頁去支持多端共用的功能,樓主親身遇到過的場景,就是圖表的繪製,咱們的方案是一個頁面,須要微信,手機網頁,和android,ios都具有該功能,並且咱們手機網頁和客戶端打開的稍微有區別,須要隱藏header。
上圖是網頁版本的,而咱們經過設置頁面的查詢參數即來自客戶端的請求或者微信的都會設置爲相似這樣的url
https://xxx.yoursites.com/page.html?hide_header=1&client=ios
而在React Native 設置webview 的代碼也很簡單,你能夠查看這裏代碼
因爲客戶端也須要大量接口的支持,所以咱們必定避免單兵做戰,須要請求時候用個fetch
,這樣其實很是不易控制數據的流入。建議在fetch上在封裝一次,這樣咱們就能夠作更多的事情,好比作統一的錯誤提示,用戶失效控制,統一設置接口請求的header,同時能夠方便咱們進行調試,在chrome中查看具體的接口數據等。
send(url,options) { var isLogin = this.isLogin(); var self = this; var defaultOptions = { method: 'GET', error: function() { options.success({'errcode':501,'errstr':'系統繁忙,請稍候嘗試'}); }, headers:{ 'Authorization': this.getAccessToken(), 'Accept': 'application/json', 'Content-Type': 'application/json', 'App': 'vanthink-ios-app' }, data:{ // prevent ajax cache if not set '_regq' : self.random() }, dataType:'json', success: function(result) {} }; var options = Object.assign({},defaultOptions,options); var httpMethod = options['method'].toLocaleUpperCase(); var full_url = ''; if(httpMethod === 'GET') { full_url = this.config.api + url + '?' + this.serialize(options.data); }else{ // handle some to 'POST' full_url = this.config.api + url; } if(this.config.debug) { console.log('HTTP has finished %c' + httpMethod + ': %chttp://' + full_url,'color:red;','color:blue;'); } options.url = full_url; var cb = options.success; // build body data if(options['method'] != 'GET') { options.body = JSON.stringify(options.data); } // todo support for https return fetch('http://' + options.url,options) .then((response) => response.json()) .then((res) => { self.config.debug && console.log(res); if(res.errcode == 101) { return self.doLogin(); } if(res.errcode != 0) { self.handeErrcode(res); } return cb(res,res.errcode==0); }) .catch((error) => { console.warn(error); }); }, handeErrcode: function(result) { // not login if(result.errcode == 123){ // your code to do return false; } return this.sendMessage(result.errstr); },
在網頁中咱們常常能夠看到很是多的小的icon,咱們習慣性的用Css Sprite 和 Icon Font或者 Svg去解決這些問題。移步到客戶端,一樣,咱們也有不少解決方案,可是有一點必需要明確,將icon放到同一個地方,方便管理。這裏有不少第三方庫選擇:
若是本身寫的話,能夠寫到一個組件中,經過設置一個基類,而後進行繼承和導出。設置不一樣的圖標思路大概以下:
import React, { TouchableHighlight,View,Text, Image, StyleSheet, PropTypes } from 'react-native'; // 基本的樣式 let styles = StyleSheet.create({ icon: { width: 21, height: 21, marginTop: 4, marginRight: 15, }, }); class Icons extends React.Component { constructor(props) { super(props); this.press = this.press.bind(this); } press() { if(typeof this.props.press == 'function') { this.props.press(); }else{ // TODO } } _renderIcon() { return ( <Image source={require('../images/baseicon.png')} style={styles.icon} /> ); } render() { return ( <TouchableHighlight underlayColor="transparent" onPress={this.press}> {this._renderIcon()} </TouchableHighlight> ); } } // 繼承 class CloseIcon extends Icons { _renderIcon() { return ( <Image source={require('../images/Delete-48.png')} style={styles.icon} /> ); } } class SearchIcon extends Icons { _renderIcon() { return ( <Image source={require('../images/Search-50.png')} style={styles.icon} /> ); } } // 導出 module.exports = { CloseIcon, SearchIcon, };
而咱們則能夠在頁面中這樣使用
import {CloseIcon,SearchIcon} from '../style/icon'; ... render() { return( //... some code <CloseIcon></CloseIcon> ); }
固然製做App中,咱們常常會遇到製做導航條的要求,
你們可使用react-native-navbar,本身寫也很是簡單,樣式大體就這些:
navBar: { height: 44, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'stretch', backgroundColor:'#fff' }, customTitle: { position: 'absolute', left: 0, right: 0, bottom: 7, alignItems: 'center', }, navBarButtonContainer: { flexDirection: 'row', justifyContent: 'center', alignItems: 'stretch', }, navBarButton: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }, navBarButtonText: { fontSize: 17, letterSpacing: 0.5, }, navBarTitleContainer: { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, justifyContent: 'center', alignItems: 'center', }, navBarTitleText: { fontSize: 17, color: '#333', fontWeight: '500', }
用法以下:
<View style={[styles.navBar,{backgroundColor: '#9b59b6'}]}> <View style={styles.navBarTitleContainer}> <Text style={[styles.navBarTitleText,{color: '#fff'}]}>NavBar3</Text> </View> <View style={[styles.navBarButtonContainer,{marginLeft:8}]}> <TouchableOpacity style={styles.navBarButton}> <View> <CloseIcon></CloseIcon> </View> </TouchableOpacity> </View> <View style={[styles.navBarButtonContainer,{marginRight:8}]}> <TouchableOpacity style={styles.navBarButton}> <View> <Text style={[styles.navBarButtonText,{color: '#fff'}]}>Done</Text> </View> </TouchableOpacity> </View> </View>
須要注意,若是設置頂部導航條,記得還有狀態欄的高度要算進去,通常設置都爲22
想了想作個 App,有下面幾個就能夠了,界面不low, 數據支撐,用戶響應便可。可是咱們在作的時候Css和Html確實解決了Bo主不會寫界面的問題,可是後面兩個咋個辦呢?因而乎官方推出了一個新的工具[Redux]()。
精煉一點就是Redux就是去去管理頁面的狀態(用戶響應)及數據(接口數據相關)。Redux中強調了三點:
單一數據源
State 是隻讀的
使用純函數來執行修改
並且Redux支持服務端,這樣更加方便咱們在進行異步的遠程數據獲取的實現。
儘管React Native 正式發佈的時間還不算很是長,可是npm上已經擁有了大量的第三方類庫,所以咱們在遇到問題或者強調快速開發的時候咱們能夠去第三方網react.parts站尋找更好的組件。本身以爲經常使用的一些以下:
react-native-search-bar
一款帶有經常使用搜索框的組件
react-native-refreshable-listview 一款帶有刷新列表組件
react-native-router-redux 一款路由和redux結合的插件,組件比較豐富
react-native-image-picker 一款選擇圖片的插件
autobind-decorator 省去每次都要聲明eventHandle.bind(this)
除了開發外,咱們還但願可以很好的調試咱們的App.默認的話,就像咱們調試咱們的web頁面同樣,咱們能夠用經常使用的console.log
,console.error
,console.warn
,因爲支持chrome調試,咱們能夠在控制檯看到打印的數據。固然,咱們也能夠真機調試,好比連上你的iPhone,須要注意的是:
你須要修改調試js的地址,在
AppDelegate.m
中將"localhost"改爲你電腦的ip就能夠了。
選中你的iPhone就能夠調試了。
固然我會持續更新,也歡迎你們pr,項目地址
最後安利一個ppt https://yunpan.cn/cqKEvrPXAS3gy (提取碼:0375)