由于国内能找到的react-native框架版本都不是最新的,在我搭建的时候遇到了很多坑都无法适用,所以在这里把我搭建的代码给大家参考一下。
首先列出各种工具的版本package.json文件:
"react": "16.9.0",
"react-native": "0.61.5",
"react-native-gesture-handler": "^1.5.1",
"react-native-reanimated": "^1.4.0",
"react-native-root-toast": "^3.2.0",
"react-native-vector-icons": "^6.6.0",
"react-navigation": "^4.0.10",
"react-navigation-redux-helpers": "^4.0.1",
"react-navigation-stack": "^1.10.3",
"react-navigation-tabs": "^2.6.0",
"react-redux": "^7.1.3",
"redux": "^4.0.4",
"redux-logger": "^3.0.6"
说明:
1.该项目使用官网的初始化方法。
2.加入了react-navigation和redux,实现了栈和tab按钮路由方式,使用redux托管了路由状态,实现了双击返回键退出程序。
3.实现了自定义iconfont的使用,但是实际使用效果不太理想,还需要大家根据需求修改,这里仅作为参考,react-native-vector-icons里边自带的推荐使用,自定义的还是更推荐使用图片代替。
4.没有引入http的相关依赖,有需要的同学可以自己加。
5.react-native是0.61.5版本,react-navigation是4.x版本,react-navigation-redux-helpers是4.x版本,react-redux是7.x版本。
运行效果:
项目结构:
下面是关键文件的代码,普通页面组件就不上代码了:
app.js
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
* @flow
*/
import React from 'react';
import { Provider } from 'react-redux'
// import { store } from './src/redux/store'
import { store2 } from './src/redux/store2'
import MainView from './src/MainView'
export default class RootApp extends React.Component {
constructor(props) {
super(props);
}
render() {
// 渲染页面
return (
)
}
}
MainView.js
import React from 'react';
import { connect } from 'react-redux'
import { View, Text, Button, StyleSheet, BackHandler } from "react-native";
import Route from "./config/route"
import {
reduxifyNavigator,
createReactNavigationReduxMiddleware,
createNavigationReducer,
createReduxContainer
} from 'react-navigation-redux-helpers'
import { store2 } from './redux/store2'
import { NavigationActions } from 'react-navigation'
import Toast from "react-native-root-toast";
const AppNavigation = createReduxContainer(Route, 'root')
const mapStateToProps = state => ({
state: state.nav
});
const NavigationLinkRedux = connect(mapStateToProps)(AppNavigation)
const TOAST_CONFIG = {
duration: 1000, // toast显示时长
position: -50, // toast位置
shadow: true, // toast是否出现阴影
animation: true, // toast显示/隐藏的时候是否需要使用动画过渡
hideOnPress: true, // 是否可以通过点击事件对toast进行隐藏
delay: 0, // toast显示的延时
onShow: () => {
// toast出现回调(动画开始时)
},
onShown: () => {
// toast出现回调(动画结束时)
},
onHide: () => {
// toast隐藏回调(动画开始时)
},
onHidden: () => {
// toast隐藏回调(动画结束时)
}
}
class MainView extends React.Component {
constructor(props) {
super(props);
this.handleBack = this.handleBack.bind(this);
}
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBack)
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBack)
}
handleBack = () => {
console.log("MainView-this.state",this.state)
console.log("MainView-this.props",this.props)
if (this.props.state.index < 1) {
if (this.lastBackPressed && this.lastBackPressed + 2000 >= Date.now()) {
// 最近2秒内按过back键,可以退出应用。
return false;
}
this.lastBackPressed = Date.now();
console.log('再按一下退出程序')
Toast.show('再按一下退出程序',TOAST_CONFIG);
return true;
}
if (this.props.state.index >= 1) {
store2.dispatch(NavigationActions.back())
}
return true;
}
render() {
return (
);
}
}
export default connect(
mapStateToProps
)(MainView);
route.js
import React from "react";
import { createAppContainer } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
// 把安卓路由动画改为从右向左滑入
import StackViewStyleInterpolator from 'react-navigation-stack/src/views/StackView/StackViewStyleInterpolator';
import {name as appName} from '../../app.json';
import TabNav from "./TabNav";
import Login from "../pages/Login"
import Register from "../pages/Register"
import FirstDetail from "../pages/FirstDetail"
const AppNavigator = createStackNavigator({
Login: {
screen: Login
},
Register: {
screen: Register
},
TabNav: {
screen: TabNav,
navigationOptions: ({navigation}) => ({
header: null
})
},
FirstDetail: {
screen: FirstDetail
},
},{
// headerMode: 'screen',
// 把安卓路由动画改为从右向左滑入
transitionConfig: ()=>({
/**
* 1、从右向左:forHorizontal
* 2、从下向上:forVertical
* 3、安卓那种的从下向上:forFadeFromBottomAndroid
* 4、无动画:forInitial
*/
screenInterpolator: StackViewStyleInterpolator.forHorizontal
}),
})
const container = createAppContainer(AppNavigator);
// AppRegistry.registerComponent(appName, () => container);
export default container;
TabNav.js
import React from 'react';
import {createAppContainer} from 'react-navigation';
// import { createBottomTabNavigator } from "react-navigation-stack";
import { createBottomTabNavigator,createMaterialTopTabNavigator } from "react-navigation-tabs";
import { View, Text, Button, StyleSheet } from "react-native";
import Ionicons from 'react-native-vector-icons/Ionicons'
import AntDesign from 'react-native-vector-icons/AntDesign'
import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons'
import IcoMoonIcon from '../assets/icomoon'
import TabHome from '../pages/Tabs/TabHome';
import TabFriend from '../pages/Tabs/TabFriend';
import TabMine from '../pages/Tabs//TabMine';
const Tab = createBottomTabNavigator(
{
TabHome: {
screen: TabHome,
navigationOptions: {
tabBarLabel: '主页',
tabBarIcon: ({tintColor, focused}) => (
//
),
}
},
TabFriend: {
screen: TabFriend,
navigationOptions: {
tabBarLabel: '统计',
tabBarIcon: ({focused, tintColor}) => (
),
}
},
TabMine: {
screen: TabMine,
navigationOptions: {
tabBarLabel: '我',
tabBarIcon: ({focused, tintColor}) => (
),
}
}
},
{
tabBarOptions: {
//当前选中的tab bar的文本颜色和图标颜色
activeTintColor: '#4BC1D2',
//当前未选中的tab bar的文本颜色和图标颜色
inactiveTintColor: '#888888',
//是否显示tab bar的图标,默认是false
showIcon: true,
//showLabel - 是否显示tab bar的文本,默认是true
showLabel: true,
//是否将文本转换为大小,默认是true
// upperCaseLabel: false,
//material design中的波纹颜色(仅支持Android >= 5.0)
pressColor: '#788493',
//按下tab bar时的不透明度(仅支持iOS和Android < 5.0).
pressOpacity: 0.8,
//tab bar的样式
style: {
backgroundColor: '#fff',
paddingBottom: 0,
borderTopWidth: 0.2,
paddingTop:0,
borderTopColor: '#ccc',
height:45,
paddingTop:0,
borderWidth:0
},
//每个tab的样式
tabStyle: {
borderWidth:0,
height:43,
},
//tab bar的文本样式
labelStyle: {
height:11,
fontSize: 11,
// margin: 1
},
//tab 页指示符的样式 (tab页下面的一条线).
indicatorStyle: {height: 0},
//是否启用滚动标签。
// scrollEnabled:true,//false,
},
//tab bar的位置, 可选值: 'top' or 'bottom'
tabBarPosition: 'bottom',
//是否允许滑动切换tab页
swipeEnabled: true,
scrollEndabled:true,
//是否在切换tab页时使用动画
animationEnabled: true,
//是否懒加载
lazy: true,
//返回按钮是否会导致tab切换到初始tab页? 如果是,则设置为initialRoute,否则为none。 缺省为initialRoute。
backBehavior: 'initialRoute',
});
const TabNav = createAppContainer(Tab);
// AppRegistry.registerComponent(appName, () => TabNav);
export default TabNav;
store2.js
import createLogger from 'redux-logger'
import { combineReducers, createStore, applyMiddleware, compose } from 'redux'
import {
reduxifyNavigator,
createReactNavigationReduxMiddleware,
createNavigationReducer
} from 'react-navigation-redux-helpers'
import Route from "../config/route"
const navReducer = createNavigationReducer(Route)
const reducers = combineReducers({nav: navReducer})
const middleware = createReactNavigationReduxMiddleware(
state => state.nav,
'root',
)
const configureStore = preloadedState => {
return createStore(
reducers,
preloadedState,
compose(
applyMiddleware(middleware, createLogger)
)
)
}
export const store2 = configureStore()