react-native开发需时肯定有tab的切换,或者页面的转调,当然用RN自身的Navigator也可以但是也不是那么方便react-navigation 就能满足很多大部分需求,如下图的三种切换方式,下面就说下TabNavigator 和StackNavigator的应用,才踏的一个坑,还是太年轻呀,横刀一撸!!!!
主要的界面 用tab 切换即是TabNavigator, 切换如下图
一共四个页面当然配置就如下咯
// 两个参数 routeConfigs: NavigationRouteConfigMap,config: TabNavigatorConfig = {}
// 一个route对应的页面和tab图标, 一个切换的样式整个tab栏的样式
//tab
export const AppNavigator = TabNavigator({
Hotshow: {screen: hotshow,navigationOptions: {
tabBarLabel: '热映',tabBarIcon: ({ tintColor,focused }) => (
<Image resizeMode='contain'
source={require('../icon/icon_hot.png')}
style={[style.footImage,{tintColor: tintColor}]}
/>
)
}},Usshow: {screen: usshow,navigationOptions: {
tabBarLabel: '北美',focused }) => (
<Image style={[style.footImage,{tintColor: tintColor}]}
resizeMode='contain'
source={require('../icon/icon_us_normal.png')}
/>
)
}},Soonshow: {screen: soonshow,navigationOptions: {
tabBarLabel: '近期',{tintColor: tintColor}]}
resizeMode='contain'
source={require('../icon/icon_soon_normal.png')}
/>
)}
},Nearcinemas: {screen: nearcinemas,navigationOptions: {
tabBarLabel: '影院',{tintColor: tintColor}]}
resizeMode='contain'
source={require('../icon/icon_near_normal.png')}
/>
)},}
},{
tabBarPosition: 'bottom',lazy: true,// 是否懒加载
initialRouteName: 'Hotshow',tabBarOptions: {
showIcon: true,pressOpacity: 0.8,style: {
height: 45,backgroundColor: '#ffffff',zIndex: 0,position: 'relative'
},labelStyle: {
fontSize: 11,paddingVertical: 0,marginTop: -4
},iconStyle: {
marginTop: -3
},tabStyle: {
backgroundColor: 'rgb(230,69,51)',},}
});
TabNavigatorConfig更多具体的参数如下
/**
* Tab Navigator
*/
export interface TabNavigatorConfig {
tabBarComponent?: React.ReactElement<any>,tabBarPosition?: 'top'|'bottom',swipeEnabled?: boolean,animationEnabled?: boolean,lazy?: boolean,tabBarOptions?: {
activeTintColor?: string,activeBackgroundColor?: string,inactiveTintColor?: string,inactiveBackgroundColor?: string,showLabel?: boolean,style?: ViewStyle,labelStyle?: TextStyle,// Top
showIcon?: boolean,upperCaseLabel?: boolean,pressColor?: string,pressOpacity?: number,scrollEnabled?: boolean,tabStyle?: ViewStyle,indicatorStyle?: ViewStyle
}
initialRouteName?: string,order?: string[],paths?: any // TODO: better def
backBehavior?: 'initialRoute'|'none'
}
如上都配置好了,就需要在屏幕上显示 ,下面代码作为展示 主要的还是创建了AppWithNavigationState 然后export 出他, 在root下调用
class AppWithNavigationState extends Component {
render() {
return(
<View style={{flex: 1}}>
{this.props.fetchbool ? <Loading/> :
<AppNavigator navigation={
addNavigationHelpers({dispatch: this.props.navigator,state: this.props.nav})
}/>
}
</View>
)
}
}
function mapStateToProeps(state){
return {
fetchbool: state.fetchload.data,nav: state.nav
}
};
function macthDispatchToProps(dispatch) {
return bindActionCreators({
navigator: navigator,initHotshowAction: initHotshow,fetchLoading: fetchLoading
},dispatch);
}
let style = StyleSheet.create({
footImage: {
width: 25,height: 25
},});
export default connect(mapStateToProeps,macthDispatchToProps)(AppWithNavigationState);
结合了redux , nav就是通过state 传递的,在redux目录下创建了一个navigators/reducer
import { NavigationActions } from 'react-navigation'; import { AppNavigator } from '../../navigators/AppNavigator'; const initialNavState = { index: 0,routes: [ { key: 'Hotshow',routeName:'Hotshow',{ key: 'Usshow',routeName:'Usshow',{ key: 'Soonshow',routeName:'Soonshow',{ key: 'Nearcinemas',routeName:'Nearcinemas',],}; export const nav = (state = initialNavState,action) => { let nextState; switch (action.type) { case 'Usshow': return AppNavigator.router.getStateForAction( NavigationActions.navigate({ routeName: 'Usshow' }),state ); case 'Soonshow': setate.index= 1 return AppNavigator.router.getStateForAction( NavigationActions.navigate({ routeName: 'Soonshow' }),state ); case 'Nearcinemas': return AppNavigator.router.getStateForAction( NavigationActions.navigate({ routeName: 'Nearcinemas' }),state ); default: //return AppNavigator.router.getStateForAction(action,state) || state; // return AppNavigator.router.getStateForAction( // state // ); return AppNavigator.router.getStateForAction( NavigationActions.navigate({ routeName: 'Hotshow' }),state ) || state ; } }
做到此处,是个tab的四个页面切换还是可以的,问题就在与当我切换到下一个页面时,就出现了状况,
在没有做进入下一个页面前,提前ajax请求,当进入了请求,当然能请求成功,但是请求成功后,刚显示的界面会还在显示等待时,尼玛返回上一个界面
这么说有点拗口,不解其意
额,,,, 清洗脱俗,惊鸿一瞥下就给直接返回A了, console.log(this.props.nav) 看看了 输出一次 nav.index = 0
然后 1 然后 0 ··········就这么又回到原点了,同时在AppWithNavigationState,解决办法想了一个在navigators/reducer里把nav传递的index固定了
export const nav = (state = initialNavState,action) => { let nextState; switch (action.type) { case 'Usshow': setate.index= 1 return AppNavigator.router.getStateForAction( NavigationActions.navigate({ routeName: 'Usshow' }),state );有次当然可以解决,但是 tab按钮不能点击咯,这真是尴尬的一幕,
当然还有个蛋疼的直接用TabNavigator 在AppWithNavigationState中的render 会运行四次,即第一个界面加载时,
console.log 输出变知道 当然这样也有办法解决,react 的生命周期呀,最前面的两个 实例化 和存在期,就在存在期入手,
shouldComponentUpdate(nextProps,nextState) { return **** ? false : true ; } componentWillUpdate(nextProps,nextState) { return *** ? false : true; }render()就减小了开销
问题是 tab还是不能点击啊!!!!!!!!
谜底是这样 StackNavigator 需要这个!!!!
export const StackNavigator = StackNavigator(
{
Tab:{screen: AppNavigator},// 就是整个tab切换的 AppNavigator
Product:{screen: DtlWebView}
},{
stackConfig:{
header: null,headerBackTitle:null,headerTintColor:'#333333',showIcon:true,swipeEnabled:false,animationEnabled:false,initialRouteName: 'Hotshow'
},mode:'card',}
);
stackConfig 主要参数
TabNavigator,StackNavigator配合应用就很好区分开了前者模块页面之间,后者Stack由字面理解就是通过栈的方式进行切换,最新的就压入到栈顶显示
在App 里之前的就改为StackNavigator
class App extends Component {
render() {
return (
<Provider store={ store }>
<StackNavigator />
</Provider>
);
}
}
到此就结束咯
不对之处,敬请更正··········