現(xiàn)在React Native已經(jīng)到了0.60+,而且0.60+是一個比較大的升級搜囱,有時間把這個項目升級一下
前言
如果是復雜項目能不用React Native就不用丑瞧,請三思! 最近公司開始重寫我們歷史悠久的iOS應用。由于iOS和安卓都是N手項目蜀肘,所以重寫绊汹。前端技術選擇了React Native。雖然我之前用React Native開發(fā)過扮宠,但是是和原生混編西乖。對于搭建一個React Native并不是特別熟悉狐榔。經(jīng)過幾天的摸索自認為弄出來個還算不太差的框架,分享出來大家一起學習获雕。只說實戰(zhàn)薄腻,沒有原理分析。這是代碼地址DLReactNativeArchitecture沒有Demo的都是流氓届案。
內(nèi)容結構
- JavaScript代碼檢測
- ESlint在VS Code下的配置
- 頁面管理
- 底部導航
- 頁面導航
- 切換導航
- 數(shù)據(jù)管理
- 全局數(shù)據(jù)管理
- 網(wǎng)絡請求錯誤管理
JavaScript代碼檢測
我個人認為這個應該是React Native開發(fā)的標配了庵楷。從我個人開發(fā)來看,在寫頁面的時候經(jīng)常忘記引用組件楣颠,這個時候并不會有提示尽纽,當你運行了項目模擬器才會告訴你錯誤,必須回去修改代碼童漩,再次運行弄贿,降低了開發(fā)效率。在代碼編寫的時候就提示書寫錯誤顯得非常重要矫膨。
ESlint在VS Code下的配置
- 在VS Code下載ESlint插件
npm i eslint-config-rallycoding babel-eslint --save-dev
- 在項目根目錄創(chuàng)建
.eslintrc
拷貝下方配置(在rules中自行配置)
{
"extends": "eslint-config-rallycoding",
"parser": "babel-eslint",
"rules": {
"semi": 0
}
}
頁面管理
用React Native開發(fā)差凹,如果想實現(xiàn)像iOS原生UITabBarController
和UINavigationController
對頁面的導航管理,只能用TabBarIOS
和NavigatorIOS
侧馅,但是這兩個組件都不支持Android(天殺的安卓)危尿。官網(wǎng)推薦了使用react-native-navigation和react-navigation,我在自己的項目中選擇了react-navigation施禾,因為?更多脚线。(寫著寫著發(fā)現(xiàn)react-navigation3.0出來了)
底部導航
// 在routes文件中
import {
createBottomTabNavigator,
createAppContainer
} from 'react-navigation'
import HomePage from '../pages/Home'
import MessagePage from '../pages/Message'
import ProfilePage from '../pages/Profile'
import styles from '../styles'
function _renderTabbarIcon(icon) {
return <Image source={icon} style={styles.tabBarIcon} />
}
const tabarIcons = {
Home: {
render: focused => {
return focused
? _renderTabbarIcon(require('../images/tabbar_home_selected.png'))
: _renderTabbarIcon(require('../images/tabbar_home.png'))
}
}
}
const tabBarStack = createBottomTabNavigator({
Home: {
screen: HomePage,
navigationOptions: {
tabBarLabel: '首頁'
}
},
Message: {
screen: MessagePage,
navigationOptions: {
tabBarLabel: '信息'
}
},
Profile: {
screen: ProfilePage,
navigationOptions: {
tabBarLabel: '我的'
}
}
}, {
defaultNavigationOptions: ({ navigation }) => ({
tabBarIcon: ({ focused }) => {
const { routeName } = navigation.state
return tabarIcons[routeName].render(focused)
}
}),
tabBarOptions: {
activeTintColor: '#6699ff',
inactiveTintColor: '#333'
}
})
export default createAppContainer(tabBarStack)
// 在App.js文件中
import TabbarStack from './src/routes'
export default class App extends Component {
render() {
return <TabbarStack />
}
}
頁面導航
第一張圖是從Home頁面跳轉到Home Detail頁面不隱藏Tabbar,第二張則是隱藏Tabbar弥搞。在代碼中我會使用
~注意~
來提示邮绿。寫注意的地方都大家可以多注意一下^^,不太通順攀例!
// 在routes文件中
const HomeStack = createStackNavigator({
Home: {
screen: HomePage,
navigationOptions: {
title: '首頁'
}
},
HomeDetail: {
screen: HomeDetailPage,
navigationOptions: {
title: '詳情'
}
}
}, {
navigationOptions: {
headerStyle: {
backgroundColor: "#fff",
borderBottomWidth: 0
},
headerTintColor: "#333",
headerBackTitle: null // ~注意~ 這個地方是隱藏返回按鈕文字的
}
})
HomeStack.navigationOptions = ({ navigation }) => { // ~注意~ 如果想實現(xiàn)隱藏Tabbar的功能要調(diào)用這個方法
let tabBarVisible = true
if (navigation.state.index > 0) {
tabBarVisible = false
}
return {
tabBarVisible
}
}
const TabBarStack = createBottomTabNavigator({
Home: {
screen: HomeStack,
navigationOptions: {
tabBarLabel: '首頁'
}
}
})
切換導航
這個主要是用于APP廣告頁面到Tabbar導航的跳轉船逮,或者是登錄頁面到Tabbar導航的跳轉。
// 在routes文件中
const switchStack = createSwitchNavigator({
Launch: {
screen: LaunchPage,
navigationOptions: {
header: null
}
},
Tabbar: {
screen: TabBarStack
}
}, {
initialRouteName: 'Launch'
})
export default createAppContainer(switchStack)
數(shù)據(jù)管理
在數(shù)據(jù)管理中我使用了react-redux, axios, redux-axios-middleware以及react-native-dropdownalert粤铭。因為涉及的文件較多挖胃,不一一列舉。其中我想說幾點梆惯,一個用戶private_token的添加酱鸭,還有就是用axios進行網(wǎng)絡請求的時候GET和POST添加參數(shù)的區(qū)別。
全局數(shù)據(jù)管理
// 在store/reducers/message.js文件
export default function reducer(state = initialState, action) {
switch (action.type) {
case FETCH_MESSAGE_LIST:
return {
...state,
loading: true,
list: [],
}
case FETCH_MESSAGE_LIST_SUCCESS:
return {
...state,
loading: false,
list: action.payload.data.items
}
case FETCH_MESSAGE_LIST_FAIL:
return {
...state,
loading: false,
error: action.error.message
}
case REMOVE_MESSAGE_WITH_ID: {
const { itemId } = action.payload
return {
...state,
list: state.list.filter(l => l.id !== itemId)
}
}
default:
return state
}
}
全局錯誤管理
在這個配置中要注意的就是垛吗,user_token
的添加凹髓。因為AsyncStorage.getItem是異步方法,所以success也要變成異步方法怯屉。
// App.js文件中
const middlewareConfig = {
interceptors: {
request: [
{
success: async function (_, req) {
// const token = await AsyncStorage.getItem('user_token')
const newReq = {
...req,
headers: {
...req.headers,
common: {
...req.headers.common,
// Authorization: token
},
}
}
return newReq
}
}
],
response: [
{
success: function (_, res) {
return res
},
error: function (_, error) {
DropDownHolder.getDropDown().alertWithType('error', 'Error', error.message)
return Promise.reject(error)
}
}
]
}
}
最后
更多詳細的代碼大家可以看源碼DLReactNativeArchitecture蔚舀。不知道這個對大家有沒有幫助饵沧,本人水平有限。寫文章條理也不是太清晰赌躺,還有些名字寫得也不是特別合適狼牺。如果大家對代碼,對文章有什么問題礼患,建議可以在評論留言是钥。大家一起學習,一起進步缅叠。
持續(xù)更新中
在開發(fā)中有遇到新的問題咏瑟。等項目差不多了,繼續(xù)更新痪署!