现在React Native已经到了0.60+,而且0.60+是一个比较大的升级,有时间把这个项目升级一下
前言
如果是复杂项目能不用React Native就不用,请三思! 最近公司开始重写我们历史悠久的iOS应用。由于iOS和安卓都是N手项目,所以重写。前端技术选择了React Native。虽然我之前用React Native开发过,但是是和原生混编。对于搭建一个React Native并不是特别熟悉。经过几天的摸索自认为弄出来个还算不太差的框架,分享出来大家一起学习。只说实战,没有原理分析。这是代码地址DLReactNativeArchitecture没有Demo的都是流氓。
内容结构
- JavaScript代码检测
- ESlint在VS Code下的配置
- 页面管理
- 底部导航
- 页面导航
- 切换导航
- 数据管理
- 全局数据管理
- 网络请求错误管理
JavaScript代码检测
我个人认为这个应该是React Native开发的标配了。从我个人开发来看,在写页面的时候经常忘记引用组件,这个时候并不会有提示,当你运行了项目模拟器才会告诉你错误,必须回去修改代码,再次运行,降低了开发效率。在代码编写的时候就提示书写错误显得非常重要。
ESlint在VS Code下的配置
- 在VS Code下载ESlint插件
npm i eslint-config-rallycoding babel-eslint --save-dev
- 在项目根目录创建
.eslintrc
拷贝下方配置(在rules中自行配置)
{
"extends": "eslint-config-rallycoding",
"parser": "babel-eslint",
"rules": {
"semi": 0
}
}
页面管理
用React Native开发,如果想实现像iOS原生UITabBarController
和UINavigationController
对页面的导航管理,只能用TabBarIOS
和NavigatorIOS
,但是这两个组件都不支持Android(天杀的安卓)。官网推荐了使用react-native-navigation和react-navigation,我在自己的项目中选择了react-navigation,因为✨更多。(写着写着发现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
}
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
}
}
页面导航
第一张图是从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 }) => { // ~注意~ 如果想实现隐藏Tabbar的功能要调用这个方法
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)
数据管理
在数据管理中我使用了react-redux, axios, redux-axios-middleware以及react-native-dropdownalert。因为涉及的文件较多,不一一列举。其中我想说几点,一个用户private_token的添加,还有就是用axios进行网络请求的时候GET和POST添加参数的区别。
全局数据管理
// 在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。不知道这个对大家有没有帮助,本人水平有限。写文章条理也不是太清晰,还有些名字写得也不是特别合适。如果大家对代码,对文章有什么问题,建议可以在评论留言。大家一起学习,一起进步。
持续更新中
在开发中有遇到新的问题。等项目差不多了,继续更新!