ReactNative开发——Navigation的使用
ReactNative开发——Navigation的使用React Native 0.43之前 ‘react-native’包里面,但0.43之后了’rea移除了rect-native’。网上的大部分资料,也是ReactNative 0.43之前的 Navigator的用法,然而我用的0.44版本在开发,这就…. 安装 ‘react-navigator’依赖于是我按着文档 https://reactnavigation.org/docs/intro/ 来安装: 在项目目录下执行命令安装: npm install --save react-navigator
结果呵呵哒: E:hybridreact_native_proProject02>npm install
npm WARN peerDependencies The peer dependency react@* included from react-navigation will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm WARN peerDependencies The peer dependency react@* included from react-native-drawer-layout-polyfill will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm WARN peerDependencies The peer dependency react@* included from react-native-tab-view will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm ERR! install trying to install 15.5.4 to E:hybridreact_native_proProject02node_modulesreact-navigationnode_modulesreact
npm ERR! install but already installed versions [ '15.5.4' ]
npm ERR! Windows_NT 10.0.14393
npm ERR! argv "D:Program Filesnodejsnode.exe" "C:UsersAdministratorAppDataRoamingnpmnode_modulesnpmbinnpm-cli.js" "install"
npm ERR! node v4.4.7
npm ERR! npm v2.15.12
npm ERR! code EPEERINVALID
npm ERR! peerinvalid The package react@16.0.0-alpha.6 does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer react-native@0.44.0 wants react@16.0.0-alpha.6
npm ERR! peerinvalid Peer react-navigation@1.0.0-beta.11 wants react@*
npm ERR! peerinvalid Peer react-test-renderer@16.0.0-alpha.6 wants react@^16.0.0-alpha.6
npm ERR! Please include the following file with any support request:
npm ERR! E:hybridreact_native_proProject02npm-debug.log```
最后我的解决办法是 安装npm3: npm install -g npm@3
然后重新执行上面的命令安装。 开始学习HelloWorld首先根据官方文档的实例代码编写出来看看效果: /** * Sample React Native App * https://github.com/facebook/react-native * @flow */
'user react'
import React,{Component} from 'react';
import {AppRegistry,View,Button,Text} from 'react-native';
import {StackNavigator} from 'react-navigation'
/** * 主页面 */
class HomeScreen extends Component {
static navigationOptions = {
/*设置标题*/
title: 'Welcome'
}
render() {
const {navigate} = this.props.navigation;
return (
<View> <Text> Hello,Navigator</Text> <Button title="Chat With Lucy" //跳转第二个页面,第二个参数,向第二个页面传入参数{user:'Lucy'} onPress={() => navigate('Chat',{user: 'Lucy'})} > </Button> </View> ); } } /** * 第二个页面 */ class ChatScreen extends Component { /*可以定义一个函数来读取上个页面传过来的参数*/ static navigationOptions = (({navigation}) => ({ title: `Chat with ${navigation.state.params.user}` })) render() { const { params } = this.props.navigation.state; return ( <View> <Text> Hello,{params.user}</Text> </View> ); } } const Project02 = StackNavigator({ Home: {screen: HomeScreen},Chat: {screen: ChatScreen},}); AppRegistry.registerComponent('Project02',() => Project02);
该代码实现了: Navigators介绍Navigators是用来定义为你应用顶用导航架构用的,你也可以通过配置让它为您渲染公共的元素,比如头部或者TabBar。 用来构建Navigator的函数
使用Navigators使用Navigators我们主要学习2个属性,下文Screen指的是我们的页面组件(即上文,HelloWorld中的HomeScreen,和ChildScreen等) 在顶层组件使用导航上面一个条目,我们讲到用 screen 的 navigation prop可以进行导航操作,但如果我们要在外部操作导航怎么办呢? const AppNavigator = StackNavigator(SomeAppRouteConfigs);
class App extends React.Component {
someEvent() {
// call navigate for AppNavigator here:
this.navigator && this.navigator.dispatch({ type: 'Navigate',routeName,params });
}
render() {
return (
<AppNavigator ref={nav => { this.navigator = nav; }} /> ); } }
注意,这种解决方案应该只用在最顶层的navigator。 Navigation 容器当navigation prop没有设置的时候,这个Navigation会自动显示在顶层,她将是一个透明的容器。 顶部Navigators接受以下属性:
下面,我贴一个例子,来演示以下 /** * Created by Administrator on 5/27/2017. */
import React from 'react';
import {
AppRegistry,Text,} from 'react-native';
import {TabNavigator,StackNavigator} from 'react-navigation';
class RecentChatsScreen extends React.Component {
render() {
return <Text>List of recent chats</Text> } } class AllContactsScreen extends React.Component { render() { return ( <View> <Text>Hello,Chat App!</Text> <Button onPress={() => this.props.navigation.navigate('Chat',{user: 'Lucy'})} title="Chat with Lucy" /> </View> ); } } class ChatScreen extends React.Component { static navigationOptions = ({navigation}) => { const {state,setParams} = navigation; const isInfo = state.params.mode === 'info'; const {user} = state.params; return { title: isInfo ? `${user}'s Contact Info` : `Chat with ${user}`,headerRight: (<Button title={isInfo ? 'Done' : `${user}'s Info`} onPress={() => setParams({mode: isInfo ? 'none' : 'info'})} />) }; }; render() { const {params} = this.props.navigation.state; return ( <View> <Text>Chat with {params.user}</Text> </View> ); } } const MainScreenNavigator = TabNavigator({ Recent: { screen: RecentChatsScreen },All: { screen: AllContactsScreen,},}); // MainScreenNavigator.navigationOptions = {title: "Main"}; const SimpleApp = StackNavigator({ // 使用 header:null 去掉StackNavigator的导航栏头部 Home: {screen: MainScreenNavigator,navigationOptions: ({navigation}) => ({header: null}),Chat: { screen: ChatScreen,//路径,user为可以接受的参数 path: 'chat1/:user',} }) const MainApp = () => <SimpleApp //设置 URL's Schema,和 Host uriPrefix={'chat://chat/'} onNavigationStateChange={(preState, newState,action) => { console.log('preState:' + JSON.stringify(preState) + ',newState:' + JSON.stringify(newState) + ',action:' + JSON.stringify(action)); }}/> AppRegistry.registerComponent('Project05',() => MainApp);
上述代码设置了 <intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT"></category>
<data android:scheme="chat" android:host="chat"></data>
</intent-filter>
安装成功之后,我们在命令行输入: 相关的ios也可以用外部URL访问本应用的页面,可以参考:https://reactnavigation.org/docs/guides/linking StackNavigatorStackNavigator用来解决屏幕跳转,用它的效果页面导航效果|类似于栈,新启动的页面覆盖在原先的页面上。 使用/** * Created by blueberry on 6/15/2017. */
import React,{Component} from 'react';
import {StyleSheet,AppRegistry} from 'react-native';
import {StackNavigator} from 'react-navigation';
class MainScreen extends Component {
static navigationOptions = {
title: 'Home',}
render() {
return (
<View style={{justifyContent: 'center',alignItems: 'center'}}> <Text>{this.props.navigation.state.params.content || ''}</Text> <Button title="Go to Profile" onPress={() => this.props.navigation.navigate('Profile',{ title: 'blueberryTitle',content: 'blueberryContent' })}/> </View> ); } } class Profile extends Component { static navigationOptions = ({navigation}) => ( { title: navigation.state.params.title,}) render() { return ( <View> <Text>{this.props.navigation.state.params.content}</Text> </View> ); } } const App = StackNavigator( /** * 路由配置 */ { Home: {screen: MainScreen},Profile: {screen: Profile,navigationOptions: {headerRight: null}},/** * StackNavigator配置,也可以省略。 */ { // 配置初始化路由名称 initialRouteName: 'Home',// 配置初始化路由的参数 initialRouteParams: {content: '初始化传入的参数'},// 配置默认的 navigationOptions navigationOptions: {headerRight: <Text>右边Header</Text>},// 转场动画开始的回到 onTransitionStart: () => { console.log('start') },} ); AppRegistry.registerComponent('Project05',() => App);
API 定义
这个函数接受2个参数,RouteConfigs和StackNavigatorConfig,其中 RoutConfigs这个路由配置类,是一个Map结构,key是路由的明城,value 是路由的配置。 StackNavigator(
{ // 以下定义了一个路由,Profile为路由的名称,对应的值则是路由的配置
Profile: {
// `ProfileScreen` 是一个 React UI组件的定义,它就是这个路由的界面
screen: ProfileScreen,// 当 `ProfileScreen` 被StackNavigator加载之后,他将会有一个`navigation` 属性。
// 这个是一个可选项,如果想让这个界面可以被外部链接启动,可以设置这个,:name是用来传入参数的,这个上文讲过。
path: 'people/:name',// 设置这个可以覆盖我们在React Component中设置的navigationOptions属性
navigationOptions: ({navigation}) => ({
title: `${navigation.state.params.name}'s Profile'`,}),...MyOtherRoutes,});
StackNavigatorConfig
Screen Navigation Options
Navigator Props我们创建StackNavigator的时候,如果想从外部给屏幕组件传入扩展的属性,可以使用 const SomeStack = StackNavigator({
// config
});
<SomeStack screenProps={/* 这个属性将传递给屏幕组件,在屏幕组件使用 this.props.screenProps就可以访问 */} />
注意这个键一定要是 screenProps,别的可不行哟。 TabNavigator用这个可以实现几个屏幕之间相互切换,(类似于android原生,TabLayout+Fragment 页面切换那种效果)。 使用/** * Created by blueberry on 6/15/2017. */
import React,AppRegistry,Image,TabBarBottom,TabView,TabBarTop} from 'react-navigation';
class HomeScreen extends Component {
static navigationOptions = {
tabBarLabel: 'Home',tabBarIcon: ({tintColor}) => (<Image source={require('./img/chat_online_talk.png')} style={[styles.icon, {tintColor: tintColor}]} />),}; render() { return ( <Button title="Go to Notification" onPress={() => this.props.navigation.navigate('Notifications')}/> ); } } class NotificationScreen extends Component { static navigationOptions = { tabBarLabel: 'Notifications',tabBarIcon: ({tintColor}) => (<Image source={require('./img/notification.png')} style={[styles.icon,// 也可以是其他React Element,// tabBarIcon: ({tintColor}) => (<Button title="按钮" onPress={() => { // }}/>),} ; render() { return ( <Button title="Go back home" onPress={() => this.props.navigation.goBack()}/> ); } } var styles = StyleSheet.create({ icon: {width: 26,height: 26} }); const App = TabNavigator( { Home: {screen: HomeScreen},Notifications: {screen: NotificationScreen} },{ tabBarOptions: { //激活的tab tint颜色 activeTintColor: '#e91e63',//没有激活的tab tint颜色 inactiveTintColor: 'black',//大写转换 upperCaseLabel: true,//显示icon showIcon: true,// android默认是TabBarTop,ios默认是TabBarBottom,tabBarComponent: TabBarBottom,// 可以为 top,bottom,用来决定TabBar放置的位置 tabBarPosition: 'bottom',//设置是否可以滑动 swipeEnabled: true,//切换时是否欧动画效果 animationEnabled: false,// 是否懒渲染tabs lazy: false,//第一个被加载的路由名称 initialRouteName: 'Home',//路由名称数组 order: ['Home','Notifications'],paths: {Home: 'home',Notifications: 'Notifications'},backBehavior: true,() => App);
Api 定义
RouteConfigs这个和StackNavigator的RouteConfigs一样,上文已经讲过,用来设置路由信息。 TabNavigatorConfig
TabBarBottom 的 tabBarOptions 设置
TabBarTop 的 tabBarOptions设置
举个栗子: tabBarOptions: {
labelStyle: {
fontSize: 12,tabStyle: {
width: 100,style: {
backgroundColor: 'blue',}
Screen Navigation Options
Navigator Props我们创建TabNavigator的时候,如果想从外部给屏幕组件传入扩展的属性,可以使用 DrawerNavigator这个导航是个抽屉效果,就是类似于QQ那种左滑菜单 使用/** * Created by blueberry on 6/15/2017. */
import React,StyleSheet,ScrollView} from 'react-native';
import {DrawerNavigator,DrawerItems} from 'react-navigation';
class HomeScreen extends Component {
static navigationOptions = {
drawerLabel: 'Home',drawerIcon: ({tintColor}) => (<Image style={[styles.icon, {tintColor: tintColor}]} source={require('./img/chat_online_talk.png')}/>),} render() { return ( <View> <Button title="Go to notifications" onPress={() => this.props.navigation.navigate('Notifications')}/> <Button title="打开抽屉" onPress={() => this.props.navigation.navigate('DrawerOpen')}/> <Button title="关闭抽屉" onPress={() => this.props.navigation.navigate('DrawerClose')}/> </View> ); } } class NotificationScreen extends Component { static navigationOptions = { drawerLabel: 'notifications',drawerIcon: ({tintColor}) => (<Image style={[styles.icon, {tintColor: tintColor}]} source={require('./img/notification.png')}/>),} render() { return ( <Button title="Go back home" onPress={() => this.props.navigation.goBack()}/> ); } } const App = DrawerNavigator( {Home: {screen: HomeScreen},Notifications: {screen: NotificationScreen}},//一下是DrawerNavigator 的配置 { // 设置宽度 drawerWidth: 300,// 设置从右边拉出,还是左边拉出 drawerPosition: 'left',//默认的的值是 DrawerItems,我们也可以自己配置组件 contentComponent: props => <ScrollView style={{borderWidth: 1,borderColor: 'red'}}><DrawerItems {...props}/></ScrollView>,contentOptions: { items: ['Home','Notification'],activeItemKey: 'key',activeTintColor: '#ff863f',activeBackgroundColor: '#d0caff',inactiveTintColor: '#000000',inactiveBackgroundColor: '#fffcf8',//这个设置了没起作用,android,api 0.45 onItemPress: (route) => { console.log('TAG' + JSON.stringify(route)) },style: null,labelStyle: null,// initialRouteName:'Notifications',} ) ; var styles = StyleSheet.create({ icon: {width: 26,height: 26} }); AppRegistry.registerComponent('Project05',() => App);
可以使用一下操作,打开或关闭抽屉 this.props.navigation.navigate('DrawerOpen'); // open drawer
this.props.navigation.navigate('DrawerClose'); // close drawer
Api定义
RouteConfigs这个和StackNavigator一样,可以参考上文。 DrawerNavigatorConfig
DrawerItems 的contentOptions
Screen Navigation Options
Navigator Props这个跟StackNavigator 和 TabNavigator的方式一样,可以参考上文。 Screen中的 Navigation 属性每个Screen都会接收这样一个属性,它其中包含了以下对象:
navigate它的函数形式为: state页面可以通过 {
// 路由的名称
routeName: 'profile',//唯一的id
key: 'main0',// 参数
params: { hello: 'world' }
}
setParams改变路由的参数 例如: class ProfileScreen extends React.Component {
render() {
const {setParams} = this.props.navigation;
return (
<Button onPress={() => setParams({name: 'Lucy'})} title="Set title name to 'Lucy'" /> ) } }
goBack关闭当前页面,并返回 示例: class HomeScreen extends React.Component {
render() {
const {goBack} = this.props.navigation;
return (
<View> <Button onPress={() => goBack()} title="Go back from this HomeScreen" /> <Button onPress={() => goBack(null)} title="Go back anywhere" /> <Button onPress={() => goBack('screen-123')} title="Go back from screen-123" /> </View> ) } }
dispatch给路由发送一个action。用个栗子(没有什么比看代码来的简单明了了)。 /** * Created by blueberry on 6/15/2017. */
import React,Text} from 'react-native';
import {NavigationActions,TabNavigator} from 'react-navigation';
class MainScreen extends Component {
render() {
return (
<View> <Button title="跳转到Child页面" onPress={() => this.props.navigation.navigate('Child')}/> <Text>{this.props.navigation.state.params ? this.props.navigation.state.params.title : ''}</Text> </View> ); } } class ChildScreen extends Component { render() { const navigationActions = NavigationActions.navigate({ routeName: 'Home',params: {title: 'blueberryTitle'} }); return ( <View> <Button title="返回" onPress={() => this.props.navigation.goBack()}/> <Button title="返回Home显示title" onPress={() => this.props.navigation.dispatch(navigationActions)}/> </View> ); } } const App = TabNavigator( {Home: {screen: MainScreen,Child: {screen: ChildScreen}} ); AppRegistry.registerComponent('NavigationUsage',() => App);
上面核心代码: const navigationActions = NavigationActions.navigate({
routeName: 'Home',params: {title: 'blueberryTitle'}
});
this.props.navigation.dispatch(navigationActions)
NavigationActions创建了一个acionts,然后使用dispatch去执行了,上面的执行效果就是,挑战到了Home页面,并传入了参数 Naviation Actions上文已经简单延时了
Navigate用法: import { NavigationActions } from 'react-navigation'
const navigateAction = NavigationActions.navigate({
routeName: 'Profile',params: {},action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigateAction)
Reset用来重新设置路由记录 const resetAction = NavigationActions.reset({
index: 1,actions: [
NavigationActions.navigate({ routeName: 'Profile'}),NavigationActions.navigate({ routeName: 'Settings'})
]
})
this.props.navigation.dispatch(resetAction
注意 index的值 必须在0 - actions.lenght的范围内,不能越界,指定当前在栈中的位置。 Back使用方法: const backAction = NavigationActions.back({
key: 'Profile'
})
this.props.navigation.dispatch(backAction)
key为路由的唯一身份,但是我设置了以后,使用 SetParamsconst setParamsAction = NavigationActions.setParams({
params: { title: 'Hello' },key: 'screen-123',})
this.props.navigation.dispatch(setParamsAction)
Screen Navigation Options配置navigatinOptions可以用2中方法来设置 navigationOptions 静态配置示例: class MyScreen extends React.Component {
static navigationOptions = {
title: 'Great',};
...
动态配置示例: class ProfileScreen extends React.Component {
static navigationOptions = ({ navigation,screenProps }) => ({
title: navigation.state.params.name + "'s Profile!",headerRight: <Button color={screenProps.tintColor} {...} />,});
这个函数接收的参数为props,props参数中包含 navigation,screenProps,navigationOptions。返回值用来决定设置的navigationOpiotns。 参数的结构如下: 一般的Navigation Options 配置方法class MyScreen extends React.Component {
static navigationOptions = {
title: 'Great',};
...
其他的配置方法可以在配置路由的时候设置:const SimpleApp = StackNavigator({
// 使用 header:null 去掉StackNavigator的导航栏头部
Home: {screen: MainScreenNavigator,navigationOptions: ({navigation}) => ({header: null}),Chat: {
screen: ChatScreen,//路径,user为可以接受的参数
path: 'chat1/:user',}
},{})
还可以在Navigation 配置中设置const App = StackNavigator(
/** * 路由配置 */
{
Home: {screen: MainScreen},navigationOptions: {headerRight: null}},/** * StackNavigator配置,也可以省略。 */
{
navigationOptions: {headerRight: <Text>右边Header</Text>},} );
示例代码地址https://github.com/blueberryCoder/RNDemo/tree/master/NavigationUsage 参考https://reactnavigation.org/docs/intro/headers (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |