Navigator管理页面的原理是借助页面栈,显示另一个页面就让这个页面入栈,返回的话就让他出栈。相比于安卓里活动之间的跳转,navigator显得非常灵活,如果将navigator作为根容器的话,那么每次跳转就是整个视图的跳转。但是也可以仅仅将navagator作为视图的一部分,比如我把视图里的组件A换成组件B。实际上,整个场景就是一个铺满的组件。
下面这个例子转自https://github.com/SpikeKing/WclNavigator/blob/master/navigator_simple.js
首先我们需要写两个组件,让第一个组件有两个可点击的控件,分别对应两种动画效果跳转到第二个组件。第二个组件有一个可点击控件,点击出栈返回第一个组件。
1.第一个组件
class FirstPage extends Component{
_press(name,type){
this.props.navigator.push({
component:SecondPage,
passProps:{
name1:name
},
type:type
});
}
render(){
return(
<View style={styles.container}>
<View style={{height: 50,justifyContent: 'center',backgroundColor:'#dd0000',alignItems:'center'}}>
<Text style={styles.text}>第一页</Text>
</View>
<TouchableOpacity
onPress={()=>this._press('来自第一页,右出','Right')}
style={{height: 50,alignItems:'center',marginTop:20}}>
<Text style={styles.text}>点击进入第二页(右出)</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={()=>this._press('来自第一页,底出','Bottom')}
style={{height: 50,alignItems:'center'}}>
<Text style={styles.text}>点击进入第二页(底出)</Text>
</TouchableOpacity>
</View>
);
}
}
可以看到这里的重点就是点击方法了,方法传入了两个参数,第一个用来表示点击的是哪个按钮,第二个是需要的动画类型。方法里是navagitor的入栈方法,这个方法接收一组参数,component就是目标组件,type是我们自定义的值,用来表示动画类型。passProps比较重要,用以向第二个组件传递数据。这里传递了一个名为name1的变量,第二个组件可以直接通过this.props.name1使用这个变量。
2.第二个组件:
class SecondPage extends Component{
_pressBack(){
this.props.navigator.pop();
}
render(){
return(
<View style={styles.container}>
<View style={{height: 50,justifyContent: 'center',backgroundColor:'#00dd00',alignItems:'center'}}>
<Text style={styles.text}>第二页:{this.props.name1}</Text>
</View>
<TouchableOpacity
onPress={()=>this._pressBack()}
style={{height: 50,alignItems:'center',marginTop:20}}>
<Text style={styles.text}>点击返回</Text>
</TouchableOpacity>
</View>
);
}
}
这里的点击方法就很简单了,就是当前组件出栈。可以看到布局里直接使用了上面传入的name1.
3.主视图(组件):
class AwesomeProject extends Component {// 初始化模拟数据
render() {
return(
<View style={{flex:1}}>
<Navigator
initialRoute={{component:FirstPage}}
configureScene={this.configureScene}
renderScene={this.renderScene}
></Navigator>
</View>
);
}
configureScene(route,routeStack){
if(route.type=='Bottom'){
return Navigator.SceneConfigs.FloatFromBottom;
} else{
return Navigator.SceneConfigs.PushFromRight;
}
}
renderScene(route,navigator){
return<route.component navigator={navigator} {...route.passProps}/>
}
}
这里要理解route,navigator只负责栈的管理,过程中值要通过route拿出。可以看到navigator需要实现三个属性,initialRoute表示初始状态显示的组件,直接传入组件名即可。configureScene表示动画效果,接收一个方法,方法接收两个参数,主要用第一个route,我在这个方法里用route.type拿出原来传入的type值并判断,返回相应的系统自带的动画效果。
renderScene是渲染方法,可以如上写死,渲染route,component,还要给这个组件传入navigator和passProps.
4.信息传递和传回:上面第一个组件通过push里的passProps将一个数据传递给了第二个组件,那么怎么从第二个组件传回第一个呢?其实原理也很简单,第一个组件想要得到第二个组件里的数据,可以向二号传递一个方法,方法接收数据参数并直接调用第一个组件的setState即可:、
在第一个组件中初始化一个属性并在渲染方法里使用:
// 构造
constructor(props) {
super(props);
// 初始状态
this.state = { message:''};
}
向第二个传入赋值方法,注意这里获取组件对象最好在方法外就得到,否则会混乱:
_press(name,type){
const me=this;
this.props.navigator.push({
component:SecondPage,
passProps:{
name1:name,
setMessage:function(message){
me.setState({message:message});
}
},
type:type
});
}
在第二个组件里通过yhis.props调用这个方法:
componentDidMount() {
if(this.props.setMessage){
this.props.setMessage('这是返回的信息');
}
}