一、前言
现在大多数的App都具备用户功能,就拿微信来说,当第一次登录时输入账号密码登录成功之后进入app主页面,此时再按返回键,原本属于前一个页面的账号输入页已经没有了,这是如何实现的?
二、安装
1、安装react-navigation
在命令行中敲入(yarn默认--save,因此不用加上)
yarn add react-navigation
或
npm i react-navigation --save
2、安装react-native-gesture-handler
yarn add react-native-gesture-handler
或
npm install --save react-native-gesture-handler
3、安装react-native-storage(可选,用于自动登录)
yarn add react-native-storage
或
npm install --save react-native-storage
4、链接依赖
react-native link
三、使用
总体思路是这样的,创建两个StackNavigation,一个包含登录前所展示的页面(登录、注册等),另一个包含登录后所展示的页面(程序主页面),然后通过react-navigation中的createSwitchNavigator(官网链接https://reactnavigation.org/docs/zh-Hans/auth-flow.html)将两个StackNavigation连起来。
完整代码:
import React, { Component } from 'react';
import {
Text,
StyleSheet,
View,
Button
} from 'react-native';
import {
createAppContainer,
createStackNavigator,
createSwitchNavigator,
createBottomTabNavigator
} from 'react-navigation';
class FirstPage extends React.Component{
constructor(props){
super(props)
this.state = {};
}
_toLogin=()=>{
this.props.navigation.navigate('Login')
}
_toRegister=()=>{
this.props.navigation.navigate('Register')
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text>First Page!</Text>
<Button
title="toLogin"
onPress={this._toLogin}
/>
<Button
title="toRegister"
onPress={this._toRegister}
/>
</View>
)
}
}
class Login extends React.Component{
constructor(props){
super(props)
this.state = {};
}
_press=()=>{
this.props.navigation.navigate('TabNav')
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text>Login!</Text>
<Button
title="模拟登录"
onPress={this._press}
/>
</View>
)
}
}
class Register extends React.Component{
constructor(props){
super(props)
this.state={}
}
_press=()=>{
this.props.navigation.navigate('Third')
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text>Register!</Text>
</View>
)
}
}
class HomeScreen extends React.Component{
constructor(props){
super(props)
this.state={}
}
_press=()=>{
this.props.navigation.navigate('Detail')
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text>这是Home页面!</Text>
<Button
title="toDetail"
onPress={this._press}
/>
</View>
)
}
}
class MeScreen extends React.Component{
constructor(props){
super(props)
this.state={}
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text>这是Me页面!</Text>
</View>
)
}
}
class Detail extends React.Component{
constructor(props){
super(props)
this.state={}
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text>这是Home页面中的Detail页面!</Text>
</View>
)
}
}
const TabNav = createBottomTabNavigator({
//这是TabNavigation,也就是屏幕底部的两个标签
Home : HomeScreen,
Me : MeScreen
})
const AuthNav = createStackNavigator({
//这是模拟验证的页面,当验证成功后在app主页面再按返回键就不会回到这些页面了,而是直接
//跳出程序
FirstPage : FirstPage,
Login : Login,
Register : Register
})
const AppNav = createStackNavigator({
//app主页面,包含一个TabNavigation和一个子页面
TabNav : TabNav,
Detail : Detail
})
export default createAppContainer(createSwitchNavigator(
{
Auth : AuthNav,
App : AppNav
},
))
四、注意项
1、
从react-navigation 2.x迁移至3.x,3.x版本对比2.x版本有了一些比较大的变化
例如说:
2.x版本不需要显式指定AppContainer,因为AppContainer在你使用createXXXNavigator(createStackNavigator、createTabNavigator....)的时候已经提供了;
3.x版本需要你显式指定AppContainer,也就是当你准备将写好的导航export出去的时候,记得在外面加一个api :createAppContainer ,如下:
export default createAppContainer(createSwitchNavigator(
{
Auth : AuthNav,
App : AppNav
},
))
还有更多变化详见(https://reactnavigation.org/blog/#breaking-changes)
2、
如果你想做自动登录,只需要在该demo上做一点小小的改变,
安装react-native-storage,这是一个在官方API AsyncStorage 上进行封装的第三方库(https://github.com/sunnylqm/react-native-storage#readme),当然你也可以选择其他你喜欢的持久化方案
yarn add react-native-storage
创建storage.js
import Storage from 'react-native-storage';
import { AsyncStorage } from 'react-native'
let storage = new Storage({
size: 1000,
storageBackend: AsyncStorage,
defaultExpires: 1000 * 3600 * 24,
enableCache: true,
});
module.exports = storage;
新增一个组件AuthLoading,作用是检查本地是否有token,有的话用这个token进行登录,然后直接跳转至主页面;没有的话显示登录注册页面
class AuthLoading extends React.Component{
constructor(props){
super(props)
this.state={}
this.loadWhichScreen()//立即执行
}
loadWhichScreen(){
storage.load({
key : 'autoLogin'
}).then((ret)=>{
//代表从本地获取token成功,接着进行自动登录
// ...此处应该是自动登录的操作,本例省略...
this.props.navigation.navigate('TabNav')
}).catch(()=>{
//表示本地没有token,显示登录注册页面
this.props.navigation.navigate('FirstPage')
})
}
render(){
return(
//这里最好有一个modal,显示操作正在进行,本例省略
null
)
}
}
修改AuthNav:
const AuthNav = createStackNavigator({
AuthLoading : AuthLoading,
FirstPage : FirstPage,
Login : Login,
Register : Register
})
修改Login中的_press方法:
_press=()=>{
storage.save({
key : 'autoLogin',
data : {
id : '123',
password : '123'
}
}).then(()=>{
this.props.navigation.navigate('TabNav')
}).catch((err)=>{
//处理错误
console.log(err)
})
}
完整代码
App.js
import React, { Component } from 'react';
import {
Text,
StyleSheet,
View,
Button
} from 'react-native';
import {
createAppContainer,
createStackNavigator,
createSwitchNavigator,
createBottomTabNavigator
} from 'react-navigation';
import storage from './storage'
class FirstPage extends React.Component{
constructor(props){
super(props)
this.state = {};
}
_toLogin=()=>{
this.props.navigation.navigate('Login')
}
_toRegister=()=>{
this.props.navigation.navigate('Register')
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text>First Page!</Text>
<Button
title="toLogin"
onPress={this._toLogin}
/>
<Button
title="toRegister"
onPress={this._toRegister}
/>
</View>
)
}
}
class Login extends React.Component{
constructor(props){
super(props)
this.state = {};
}
_press=()=>{
storage.save({
key : 'autoLogin',
data : {
id : '123',
password : '123'
}
}).then(()=>{
this.props.navigation.navigate('TabNav')
}).catch((err)=>{
//处理错误
console.log(err)
})
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text>Login!</Text>
<Button
title="模拟登录"
onPress={this._press}
/>
</View>
)
}
}
class Register extends React.Component{
constructor(props){
super(props)
this.state={}
}
_press=()=>{
this.props.navigation.navigate('Third')
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text>Register!</Text>
</View>
)
}
}
class HomeScreen extends React.Component{
constructor(props){
super(props)
this.state={}
}
_press=()=>{
this.props.navigation.navigate('Detail')
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text>这是Home页面!</Text>
<Button
title="toDetail"
onPress={this._press}
/>
</View>
)
}
}
class MeScreen extends React.Component{
constructor(props){
super(props)
this.state={}
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text>这是Me页面!</Text>
</View>
)
}
}
class Detail extends React.Component{
constructor(props){
super(props)
this.state={}
}
render(){
return(
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<Text>这是Home页面中的Detail页面!</Text>
</View>
)
}
}
class AuthLoading extends React.Component{
constructor(props){
super(props)
this.state={}
this.loadWhichScreen()//立即执行
}
loadWhichScreen(){
storage.load({
key : 'autoLogin'
}).then((ret)=>{
//代表从本地获取token成功,接着进行自动登录
// ...此处应该是自动登录的操作,本例省略...
this.props.navigation.navigate('TabNav')
}).catch(()=>{
//表示本地没有token,显示登录注册页面
this.props.navigation.navigate('FirstPage')
})
}
render(){
return(
//这里最好有一个modal,显示操作正在进行
null
)
}
}
const TabNav = createBottomTabNavigator({
//这是TabNavigation,也就是屏幕底部的两个标签
Home : HomeScreen,
Me : MeScreen
})
const AuthNav = createStackNavigator({
//这是模拟验证的页面,当验证成功后在app主页面再按返回键就不会回到这些页面了,而是直接
//跳出程序
AuthLoading : AuthLoading,
FirstPage : FirstPage,
Login : Login,
Register : Register
})
const AppNav = createStackNavigator({
//app主页面,包含一个TabNavigation和一个子页面
TabNav : TabNav,
Detail : Detail
})
export default createAppContainer(createSwitchNavigator(
{
Auth : AuthNav,
App : AppNav
},
))
创建storage.js
import Storage from 'react-native-storage';
import { AsyncStorage } from 'react-native'
let storage = new Storage({
size: 1000,
storageBackend: AsyncStorage,
defaultExpires: 1000 * 3600 * 24,
enableCache: true,
});
module.exports = storage;
五、结语
本文较为详细地展示了如何使用react-navigation实现身份认证,希望能够帮助到有需要的人。
网友评论