1. 背景
通常一個(gè)應(yīng)用不會(huì)由單個(gè)界面組成壕曼,而是由多個(gè)模塊枣氧、多個(gè)頁面組成剩胁。react-navigation的功能就是負(fù)責(zé)RN導(dǎo)航條管理昂利、頁面跳轉(zhuǎn)以及中間的交互過程缚陷,這篇文章主要圍繞這個(gè)方案的使用介紹适篙。
2. 安裝
# 項(xiàng)目根目錄安裝
yarn add react-navigation
# or with npm
# npm install react-navigation
npm install --save react-navigation
npm install --save react-native-gesture-handler
注意:不同RN版本會(huì)有特定的配置,例如下面是大于0.60的注意點(diǎn)箫爷。
if you're on React Native >= 0.60, you need to disable autolinking for react-native-gesture-handler first.
更詳細(xì)可參考安裝教程
3. 使用
在react-navigation中有以下類型導(dǎo)航器:
- StackNavigator: 類似于普通的Navigator嚷节,屏幕上方導(dǎo)航欄;
- TabNavigator: 相當(dāng)于iOS里面的TabBarController虎锚,屏幕下方的標(biāo)簽欄硫痰;
- DrawerNavigator: 抽屜效果,側(cè)邊滑出窜护;
- SwitchNavigator
- ...
創(chuàng)建
幾種導(dǎo)航器的創(chuàng)建方式是相似的效斑,這里以創(chuàng)建 StackNavigator 為例。
現(xiàn)在定義HomeComp組件路由為Home柱徙,LoginComp組件路由為L(zhǎng)ogin缓屠,LoginComp為默認(rèn)第一個(gè)顯示的組件。
# 創(chuàng)建底部標(biāo)簽欄為: const RootStack = createBottomTabNavigator(...)
# 創(chuàng)建測(cè)滑為: const RootStack = createDrawerNavigator(...)
# 創(chuàng)建上方導(dǎo)航欄
const RootStack = createStackNavigator(
{
Home:{//路由
screen:HomeComp,//對(duì)應(yīng)組件
},
Login:{
screen:LoginComp
}
},
{
initialRouteName: 'Login', //第一個(gè)顯示組件頁面,填路由
//默認(rèn)全局配置
// defaultNavigationOptions: {
// headerStyle: {
// backgroundColor: '#f4511e',
// },
// headerTintColor: '#fff',
// headerTitleStyle: {
// fontWeight: 'bold',
// },
// }
}
)
const AppContainer = createAppContainer(RootStack);//創(chuàng)建容器
export default class App extends React.Component<IAppProps> {
render() {
return (
<AppContainer />
)
}
}
跳轉(zhuǎn)&傳參
定義好路由之后坐搔,我們就可以嘗試跳轉(zhuǎn)了藏研。跳轉(zhuǎn)主要用的是StackActions
方法,我們可以通過它傳入路由和參數(shù)進(jìn)行跳轉(zhuǎn)概行。
StackActions.push({routeName, params, action, key})
根據(jù)具體業(yè)務(wù)的不同蠢挡,會(huì)有不同的跳轉(zhuǎn)行為,StackActions跳轉(zhuǎn)行為有下面幾種:
方法 | 用法 | 例子 |
---|---|---|
push | 導(dǎo)航到堆棧中的一個(gè)新的路由 | [A , B] push C == [A , B , C] |
pop | 返回堆棧中的上一個(gè)頁面 | [A, B] pop == [A] |
popToTop | 返回堆棧中的第一個(gè)頁面 | [A, B,C] popToTop == [A] |
replace | 用新路由替換當(dāng)前路由 | [A , B] replace C == [A , C] |
reset | 擦除導(dǎo)航器狀態(tài)并將其替換為多個(gè)操作的結(jié)果 | [A , B] reset C == [C] |
并且需要我們傳入對(duì)應(yīng)參數(shù)凳忙。
參數(shù)解釋
- routeName:要跳轉(zhuǎn)到的界面的路由名业踏,也就是在createStackNavigator中配置的路由名;
- params:要傳遞給下一個(gè)界面的參數(shù)涧卵,可選勤家;
- action:如果該界面是一個(gè)navigator的話,將運(yùn)行這個(gè)sub-action柳恐,可選伐脖;
- key:要導(dǎo)航到的路由的可選標(biāo)識(shí)符。 如果已存在乐设,將后退到此路由讼庇,可選。
案例
# 跳轉(zhuǎn)Home組件&傳入?yún)?shù):
StackActions.push({routeName:'Home',params:{name:'張三'}})
# or
NavigationActions. navigation({routeName:'Home'})
# or
this.props.navigation.navigate('Home', { /* params go here */ })
# Home組件獲取跳轉(zhuǎn)參數(shù)
const ops = this.props.navigation.getParam('params')
# or
const ops = this.props.navigation.state.params
除此之外近尚,navigationActions也包含部分跳轉(zhuǎn)方法蠕啄。
NavigationActions.navigation ({routeName, params, action, key})
方法 | 用法 | 例子 |
---|---|---|
navigation | 跳轉(zhuǎn)到當(dāng)前堆棧路由里存在的一個(gè)頁面 | [A , B,C, D] navigate B == [A, B] |
Back | 返回到上一個(gè)頁面 | [A, B] Back == [A] |
popToTop | 返回堆棧中的第一個(gè)頁面 | [A, B,C] popToTop == [A] |
Set Params | 設(shè)置指定頁面的Params | ** |
Init | 初始化一個(gè) state 如果 state 是 undefined | ** |
header bar設(shè)置
默認(rèn)導(dǎo)航跳轉(zhuǎn)的頁面是不帶頭部導(dǎo)航欄的再来,需要我們?cè)诮M件里面進(jìn)行設(shè)置个粱。
每個(gè)頁面組件可以有一個(gè)名為navigationOptions
的靜態(tài)屬性邓嘹,它是一個(gè)對(duì)象或一個(gè)返回包含各種配置選項(xiàng)的對(duì)象的函數(shù)笼平,下面是一個(gè)操作實(shí)例殖侵。
class Home extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
//title:'標(biāo)題'
headerTitle: <headerTitle/>,//自定義中間標(biāo)題控件
headerRight: <LeftButton event={()=>{navigation.getParam('back')}}/>,//自定義左邊控件
headerLeft: <RightButton/>,//自定義右邊控件
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
};
};
componentDidMount() {
this.props.navigation.setParams({ back: this. _back });
}
_back = () => {
alert('back')
};
}
需要注意的是:
由于navigationOptions 是個(gè)static方法夺饲,不能直接拿到this對(duì)象里的方法胡陪,需要先通過this.props.navigation.setParams設(shè)置件舵,navigationOptions里通過navigation.getParam('back')獲取叹卷。
headerStyle撼港、headerTintColor、headerTitleStyle等屬性也可以直接在createStackNavigator全局設(shè)置骤竹。
模態(tài)跳轉(zhuǎn)
如果需要模態(tài)跳轉(zhuǎn)則需要修改配置帝牡。
const RootStack = createStackNavigator(
{
Main: {
screen: MainStack,
},
MyModal: {
screen: ModalScreen,
},
},
{
mode: 'modal',
headerMode: 'none',
}
);
4. 多模塊跳轉(zhuǎn)
通常在同一個(gè)模塊下面不容易出現(xiàn)路由重名的情況,這種情況通常出現(xiàn)在多個(gè)模塊開發(fā)蒙揣。并且當(dāng)跳轉(zhuǎn)只寫了一個(gè)路由名字時(shí)靶溜,是不清楚跳轉(zhuǎn)到哪個(gè)模塊下面的頁面,缺乏可讀性懒震。因此在react-navigation基礎(chǔ)上罩息,筆者團(tuán)隊(duì)做了一套簡(jiǎn)單的處理路由的邏輯。
- 每一個(gè)模塊下面會(huì)有一個(gè)routes.ts的文件个扰。在項(xiàng)目初始化時(shí)瓷炮,會(huì)獲取所有模塊下route.ts文件里定義的路由和對(duì)應(yīng)組件,并根據(jù)對(duì)應(yīng)模塊名字拼接路由路徑递宅。例如在home模塊目錄有個(gè)routes.ts娘香。下面的詳情路由經(jīng)過處理后的真實(shí)路由為home/homeDetail。
# home模塊下router.ts文件
export default [
{
path: '/homeDetail',
component: HomeDetail,
},
{
path: '/home',
component: Home
},
]
將1步驟中所有處理好的路由和相關(guān)配置在createStackNavigator中定義好办龄。
封裝一個(gè)負(fù)責(zé)跳轉(zhuǎn)的類topNavigator(內(nèi)部是StackActions和navigationActions跳轉(zhuǎn))烘绽,對(duì)于外部而言傳入?yún)?shù)分別為模塊名字,路由俐填,參數(shù)安接。
topNavigator.push(模塊名, 路由名, 參數(shù)})
# demo
topNavigator.push('home', '/homeDetial', {params: params})
topNavigator.replace(__onamespace, '/add-members', {params: params})
topNavigator.back()
- 又或者是每個(gè)模塊下面再創(chuàng)建一個(gè)文件暴露跳轉(zhuǎn)方法,如下示例英融,這樣就基本完成多個(gè)模塊間的路由跳轉(zhuǎn)問題盏檐。
/**
* 跳轉(zhuǎn)到首頁詳情
*/
export default function goHomeDetail(detailOps: HomeDetaiOps) {
topNavigator.push(__onamespace, '/homeDetail', { params: detailOps });
}
# 其他模塊文件跳轉(zhuǎn)直接調(diào)用goHomeDetail(...)
5. url跳轉(zhuǎn)
動(dòng)態(tài)解析服務(wù)器下發(fā)路由也是界面跳轉(zhuǎn)常用的一種方式,因此可以定義一套協(xié)議驶悟,例如:
pa://XX/home/homedetail?name='zhangsan'&age=10
胡野。客戶端做一個(gè)專門解析路由的類撩银,將url解析模塊名字為home给涕,路由路徑為homedetail豺憔,參數(shù)為name和age额获,再執(zhí)行跳轉(zhuǎn)方法够庙。這樣就能成功跳轉(zhuǎn)到home模塊下面的homeDetail頁面,搞定抄邀!