title: 翻譯|React-navigation導航系統(2)
date: 2017-03-28 07:48:36
categories: 翻譯
tags: React-native
Navigators
Navigators允許你定義你的導航結構.Navigators也可以渲染普通的元素,例如你配置好的header和tab bar.
navigators可以是單純的React組件.
內建的Navigators
react-navigation
包含下面的幾個函數幫助你創建navigators:
-
StackNavigator
-一次渲染一個screen,在screen之間切換.當一個新的screen被打開的時候,他被放在棧頂. -
TabNavigator
-渲染出一個tab bar讓用戶可以在多個screen之間切換. -
DrawNavigator
-渲染一個抽屜,可以從屏幕左邊側滑出.
使用Navigators渲染screen
navigators實際渲染的就是React組件
了解怎么創建screen,讀讀一下內容:
- Screen
navigation
props允許screen分發navigation動作,例如操作另外一個screen. - Screen
navigationOptions
定制screen的展示方式(例如:header title,tab label)
在頂層組件上調用導航
萬一你想在同一級別的Navigation screen之間使用Navigator,你可以使用react的ref
選項:
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 Containers
如果navigators沒有props的話,他就會表現為頂層navigators.這個方式提供了一個透明的navigator container,這是頂層導航props的來源.
當渲染其中一個navigators的時候,navigation prop是可選的.如果沒有navigation prop,container將會管理自己的導航state.他也可以使用URLs,外部鏈接以及整合android的back button.
為了使用方便,在幕后內建的navigators有這個能力,因為在幕后他們使用了createNavigationContainer
.通常,navigators需要一個navigation prop來執行一定的功能.
onNavigationStateChange(prevState, newState)
當navigation state由頂層navigator變化管理的時候,這一點非常有用.為了達到這個目的,這個函數在每次調用的時候都會使用導航之前的state和導航之后的新state作為參數.
containerOptions
當一個navigator在頂層被使用的時候,這些選項可以來配置這個navigator.
如果一個navigator配置了containerOptions
,但是也接受了navigation
prop,會拋出錯誤.因為在這種情況下,navigator有兩種選擇,它就不知道怎么做了.
-
URIPrefic
-app可以處理的URI前綴.在處理deep link
的時候,可以提取路徑,并且傳遞到router.
StackNavigator
給你的app提供screen之間轉變的方法,每個轉變到的screen會存放在堆棧的棧頂.
默認情況下,StackNavigator配置有iOS和android的外觀和感覺:在iOS下,新的screen從屏幕的右側滑入,在android下,新的screen從底部淡入.iOS下也可以配置為從屏幕底部滑入.
class MyHomeScreen extends React.Component {
static navigationOptions = {
title: 'Home',
}
render() {
return (
<Button
onPress={() => this.props.navigation.navigate('Profile', {name: 'Lucy'})}
title="Go to Lucy's profile"
/>
);
}
}
const ModalStack = StackNavigator({
Home: {
screen: MyHomeScreen,
},
Profile: {
path: 'people/:name',
screen: MyProfileScreen,
},
});
定義API
StackNavigator(Routeconfigs,StackNavigatorConfig)
RouteConfigs
route的配置對象是route name到route config的映射(譯者:這才是重點),配置對象告訴navigator什么來代表route.
StackNavigator({
// For each screen that you can navigate to, create a new entry like this:
Profile: {
// `ProfileScreen` is a React component that will be the main content of the screen.
screen: ProfileScreen,
// When `ProfileScreen` is loaded by the StackNavigator, it will be given a `navigation` prop.
// Optional: When deep linking or using react-navigation in a web app, this path is used:
path: 'people/:username',
// The action and route params are extracted from the path.
// Optional: Override the `navigationOptions` for the screen
navigationOptions: {
title: ({state}) => `${state.params.username}'s Profile'`,
},
},
...MyOtherRoutes,
});
StackNavigatorConfig
Router的Options:
-
initialRouteName
-設定默認的堆棧的screen.需要和route config的鍵之一相同. -
initalRouteParams
-初始化route的參數 -
navigationOptions
-默認需要使用的可選參數 -
path
-覆蓋route configs的路徑設置
可視化選項:
-
mode
-定義渲染和切換之間的樣式:-
card
-使用iOS和android標準的切換方法.默認值 -
modal
-使screen從底部滑動顯示.僅僅在iOS下使用,Andorid下沒有效果
-
-
headerMode
-定制header渲染的方法-
float
-切換界面的時候,用動畫效果在screen的頂部渲染header -
screen
-每一個screen都有一個header附著到頭部,切換的時候有淡入和淡出的效果.andorid的基本模式 -
none
-沒有header的渲染.
-
cardStyle
-使用這個prop來重寫或者擴展單個card的默認styleonTransitionStart
-當card開始切換動畫的時候,這個函數被調用onTransitionEnd
-當切換動畫完成的時候,這個函數被調用
Screen Navigation Options
通常在screen組件中定義靜態的navigationOptions
.例如:
class ProfileScreen extends React.Component {
static navigationOptions = {
title: ({ state }) => `${state.params.name}'s Profile!`,
header: ({ state, setParams }) => ({
// Render a button on the right side of the header
// When pressed switches the screen to edit mode.
right: (
<Button
title={state.params.editing ? 'Done' : 'Edit'}
onPress={() => setParams({editing: state.params.editing ? false : true})}
/>
),
}),
};
...
所有的stackNavigator
的navigationOptions
:
-
title
-scene的標題(字符串) -
header
-header bar的配置對象-
visible
-header可視性的切換.只有當headerMode
是screen
的時候才可以工作 -
title
-header可以使用的字符串或者React組件,默認是scene的title
-
backTitle
-iOS back按鈕的title字符串或者null
到disable標簽,默認設定到scene的title
. -
right
-顯示在header右側的React組件 -
left
-同上,左側 -
style
-header的Style對象 -
titleStyle
-title組建的Style對象 -
tintColor
-header的著色
-
-
cardStack
-card stack的配置對象-
gesturesEnabled
-不管你是不是用手勢,在iOS上是true,在android里是false.
-
Navigator Props
由StackNavigator(...)
創建的navigator組件接收兩個props:
screenProps
-向下傳遞到子screen,例如:
const SomeStack = StackNavigator({
// config
});
<SomeStack
screenProps={/* this prop will get passed to the screen components as this.props.screenProps */}
/>
Examples
看看實例SimpleStack.js和ModalStack.js,可以在本地的NavigationPlaygroundapp中運行.
TabNavigator
通常很容易使用TabRouter來創建有幾個tabs的screen.
class MyHomeScreen extends React.Component {
static navigationOptions = {
tabBar: {
label: 'Home',
// Note: By default the icon is only shown on iOS. Search the showIcon option below.
icon: ({ tintColor }) => (
<Image
source={require('./chats-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
},
}
render() {
return (
<Button
onPress={() => this.props.navigation.navigate('Notifications')}
title="Go to notifications"
/>
);
}
}
class MyNotificationsScreen extends React.Component {
static navigationOptions = {
tabBar: {
label: 'Notifications',
icon: ({ tintColor }) => (
<Image
source={require('./notif-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
},
}
render() {
return (
<Button
onPress={() => this.props.navigation.goBack()}
title="Go back home"
/>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 26,
height: 26,
},
});
const MyApp = TabNavigator({
Home: {
screen: MyHomeScreen,
},
Notifications: {
screen: MyNotificationsScreen,
},
}, {
tabBarOptions: {
activeTintColor: '#e91e63',
},
});
定義API
TabNavigator(RouteConfigs,TabNavigator)
RouteConfigs
route的配置對象是route name到route config的映射(譯者:這才是重點),配置對象告訴navigator什么來代表route.
TabNavigatorConfig
-
tabBarComponent
-作為tab bar的組件.例如,TabView.TabBarBottom
(ios的默認配置),TabView.TabBarTop
(android的默認配置) -
tabBarPosition
-tab bar的位置,可以是top
和bottom
-
swipeEnabled
-是否在tab之間滑動 -
animationEnabled
-變換tabs的時候是否開啟動畫效果 -
lazyLoad
-是否在需要的時候才惰性加載tabs,代替預渲染 -
tabBarOption
-配置tab bar,看下面
幾個Options可以傳遞到潛在的的router,修改導航的邏輯 -
initialRouteName
-初始化時加載的tab route -
order
-定義tabs順序的routeName的數組 -
paths
-提供routeName到path配置的映射,重寫routeConfigs里的paths設置 -
backBehavior
-back button是不是應該導致tab切換到初始的tab?入如果是的話,設定initialRoute
,否則就是none
.默認到initialRoute
的行為.
TabBarTop
的tabBarOptions
設置(android默認的tab bar)
-
activeTintColor
-激活tab的標簽和icon的顏色 -
inactiveTintColor
-未激活tab的標簽和icon的顏色 -
showIcon
-是否在tab中顯示icon,默認是false -
showLabel
-是否在tab顯示label,默認是true -
upperCaseLabel
-tab的label是否是大寫,默認是true -
pressColor
-material漣漪效果的顏色(Android>=5.0) -
pressOpacity
-按下tab的透明度變化(iOS和Android<5.0) -
scrollEnabled
-是否是滑動式tabs. -
tabStyle
-tab的樣式配置對象 -
indicatorStyle
-tab指示器的樣式對象(tab底部的劃線) -
labelStyle
-tab label的樣式對象 -
style
-tab bar的樣式對象
實例:
tabBarOptions: {
labelStyle: {
fontSize: 12,
},
style: {
backgroundColor: 'blue',
},
}
Screen導航的選項
通常在screen組件中定義靜態的navigationOptions
.例如:
class ProfileScreen extends React.Component {
static navigationOptions = {
title: ({ state }) => `${state.params.name}'s Profile!`,
tabBar: ({ state, setParams }) => ({
icon: (
<Image src={require('./my-icon.png')} />
),
}),
};
...
所有TabNavigator
的navigationOption
:
-
title
-scene的title(字符串) -
tabBar
-tab bar的config對象:-
visible
-tab bar的可見性的切換 -
icon
-React組件或者函數給出{focused:boolean,tintColor:string}
,返回一個React組件,顯示在tab bar -
label
-顯示在tab bar中的tab的名字.如果定義為undefined,scene的title
會被使用.如果要隱藏,看前面部分的tabBarOption.showLabel
.
-
Navigator Props
由TabNavigator(...)
創建的navigator組件接收下面的props:
-
screenProps
-向下傳遞額外的options給子screen,例如:
const TabNav = TabNavigator({
// config
});
<TabNav
screenProps={/* this prop will get passed to the screen components as this.props.screenProps */}
/>
抽屜式導航
用來構建抽屜式導航
class MyHomeScreen extends React.Component {
static navigationOptions = {
drawer: () => ({
label: 'Home',
icon: ({ tintColor }) => (
<Image
source={require('./chats-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
}),
}
render() {
return (
<Button
onPress={() => this.props.navigation.navigate('Notifications')}
title="Go to notifications"
/>
);
}
}
class MyNotificationsScreen extends React.Component {
static navigationOptions = {
drawer: () => ({
label: 'Notifications',
icon: ({ tintColor }) => (
<Image
source={require('./notif-icon.png')}
style={[styles.tabIcon, {tintColor: tintColor}]}
/>
),
}),
}
render() {
return (
<Button
onPress={() => this.props.navigation.goBack()}
title="Go back home"
/>
);
}
}
const styles = StyleSheet.create({
icon: {
width: 24,
height: 24,
},
});
const MyApp = DrawerNavigator({
Home: {
screen: MyHomeScreen,
},
Notifications: {
screen: MyNotificationsScreen,
},
});
打開抽屜或者關閉抽屜,分別導航到DrawerOpen
和Drawerclose
.
this.props.navigation.navigate('DrawerOpen'); // open drawer
this.props.navigation.navigate('DrawerClose'); // close drawer
定義API
DrawerNavigator(RouteConfigs, DrawerNavigatorConfig)
RouteConfigs
參看前面的內容
DrawerNavigatonConfig
-
drawerWidth
-抽屜的寬度 -
drawerPosition
-選項是left
和right
.默認是left
. -
contentComponent
-用來渲染抽屜內容的組件,例如,navigation item.接收navigation
prop.默認是DrawerView.Items
.了解更多內容看下面內容. -
contentOptions
-配置drawer的內容,看下面內容
幾個選項傳遞給潛在的router,用來修改navigation的邏輯: -
initialRouteName
-初始化route的routeName -
order
-定義drawer item順序的routeName數組 -
path
-提供一個routeName到path config的映射,重寫掉routeConfigs中的path配置 -
backBehavior
-back按鈕一定要返回到初始化的route嗎?如果是的話,設置到initialRoute
,否則就用none
.默認到initialRoute
的行為.
提供定制化的contentComponent
可以使用react-navigation
重寫默認的組件.
const CustomDrawerContentComponent = (props) => (
<View style={style.container}>
<DrawerView.Items {...props} />
</View>
);
const styles = StyleSheet.create({
container : {
flex : 1,
},
});
DrawerView.Item
的contentOptions
配置
-
activeTintColor
-激活的標簽的label和icon的顏色 -
activeBackgroundColor
-激活的標簽的背景顏色 -
inactiveTintColor
-未激活的標簽的label和icon的顏色 -
inactiveBackgroundColor
-未激活的標簽的背景顏色 -
style
-內容部分的樣式對象
示例:
contentOptions: {
activeTintColor: '#e91e63',
style: {
marginVertical: 0,
}
}
Screen導航的選項
通常在組件中定義靜態的navigationOptions
.
class ProfileScreen extends React.Component {
static navigationOptions = {
title: ({ state }) => `${state.params.name}'s Profile!`,
drawer: {
icon: (
<Image src={require('./my-icon.png')} />
),
},
};
...
所有的DrawerNavigation
navigationOption
配置項
-
title
-scene的標題 -
drawer
-drawer的配置對象-
label
-字符串,React組件或者函數被設定{fcoused:boolean,tinColor:string}
返回一個React組件,顯示在drawer的邊欄上.當label定義為undefined時,scene的``title被使用. -
icon
-React組件或者函數被設定為{fcoused:boolean,tintColor:string}
返回一個React元素,顯示在drawer的邊欄上.
-
Navigator 的Props
由DrawerNavigator(...)
創建的navigator組件接受下面的props:
-
screenProps
-向下傳遞額外的options到子screen,例如:
const DrawerNav = DrawerNavigator({
// config
});
<DrawerNav
screenProps={/* this prop will get passed to the screen components as this.props.screenProps */}
/>
Screen Navigation Prop
app中的每個screen都接收navigation prop 包含下面的內容:
-
navigate
-(helper)鏈接的其他的screens -
state
-screen的當前state和routes -
setParam
-(helper)改變route的參數 -
goBack
-(helper)關閉激活的screen并且返回 -
dispatch
-發送一個action到router
Navigation Actions
所有的Navigation Actions都會返回一個對象,這個對象可以使用navigation.dispatch
方法傳遞到router.
注意:如果你想dispatch react-navigation,你應該使用這個庫提供的action creators.
下面的actions是可以使用的:
-
Navigate
-導航到其他的route -
Reset
-使用新的state代替目前的state -
Back
-返回上一個state -
Set Params
-給定的route設置參數 -
Init
-如果state沒有定義,用來初始化第一個state
Navigate
Navigatie action
會使用Navigate action
的結果來更新當前的state.
-
routeName
-字符串-必選項,在app的router里注冊的導航目的地的routeName. -
params
-對象-可選項-融合進目的地route的參數 -
actions
-對象-可選項-(高級)-如果screen也是一個navigator,次級action可以在子router中運行.在文檔中描述的任何actions都可以作為次級action.
import { NavigationActions } from 'react-navigation'
const navigateAction = NavigationActions.navigate({
routeName: 'Profile',
params: {},
action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigateAction)
Reset
Reset
action刪掉所有的navigation state并且使用幾個actions的結果來代替.
-
index
—數組-必選-navigationstate
中route
數組中激活route的index. -
actions
-數組-必選項-Navigation Actions數組,將會替代navigation state
import { NavigationActions } from 'react-navigation'
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'Profile'})
]
})
this.props.navigation.dispatch(resetAction)
怎么使用index
參數
index
參數被用來定制化當前激活的route
例如:使用兩個routes Profile
和Settings
給一個基礎的stakc navigation設置.為了重置route到經過Settings
的激活screen那一點,但是在堆棧中他又存放在Setting
screen之上,你可以這么做:
import { NavigationActions } from 'react-navigation'
const resetAction = NavigationActions.reset({
index: 1,
actions: [
NavigationActions.navigate({ routeName: 'Profile'}),
NavigationActions.navigate({ routeName: 'Settings'})
]
})
this.props.navigation.dispatch(resetAction)
Back
返回到前一個screen并且關閉當前screen.back
action creator接受一個可選的參數:
-
key
-字符串或者空-可選項-如果設定了,navigation將會從設定的key返回.如果是null,navigation將返回到任何地方.
import { NavigationActions } from 'react-navigation'
const backAction = NavigationActions.back({
key: 'Profile'
})
this.props.navigation.dispatch(backAction)
SetParams
當dispatching setParams的時候
,router將會產出一個新的state,這個state是已經改變了特定route的參數,以key作為身份驗證
-
params
-對象-必選參數-融合進已經存在的route參數中的新參數 -
key
-字符串-必選參數-Route的key,應該分配給新的參數
import { NavigationActions } from 'react-navigation'
const setParamsAction = NavigationActions.setParams({
params: { title: 'Hello' },
key: 'screen-123',
})
this.props.navigation.dispatch(setParamsAction)
Screen Navigation Options
每個screen都可以配置幾個方面的內容,這些內容影響到在父navigators中怎么得到展示.
定制每一個可選項的兩種方法
靜態配置方法:每一個navigation 可選項都可以被直接設定:
class MyScreen extends React.Component {
static navigationOptions = {
title: 'Great',
};
...
動態配置方法
要么就采用函數式的方法,接受參數,然后返回可選項的值.
-
navigation
-screen的navigation prop和navigation.state
中screen的route -
childRouter
-如果screen是一個navigator,這個參數就是子代router.
class ProfileScreen extends React.Component {
static navigationOptions = {
title: (navigation, childRouter) => {
return navigation.state.params.name + "'s Profile!";
},
};
...
通用的Navigation Options
navigation的可選項title
在每一個navigator之間是通用的,用來設定每一個screen的標題字符串.
class MyScreen extends React.Component {
static navigationOptions = {
title: 'Great',
};
...
不像其他的navigation的可配置項僅僅由navigator view來使用,title 選項可以被環境變量使用來更新瀏覽器的標題或者app切換時候的標題.
默認的Navigation選項
在screen中定義navigationOption
非常普遍,但是有時候在navigator中定義navitationOptions
也是非常有用
想象下面的場景:你的TabNavigator
代表app中的一個screen.他在頂層StackNavigator
之內:
StackNavigator:
- route1: A screen
- route2: A TabNavigator
現在route2
是激活的,你可能會隱藏header,隱藏route1
的header非常容易,route2
的header應該也很容易隱藏.這就是默認Navigation Option 要做的.可以在navigationOptions
中設定:
TabNavigator({
profile: ProfileScreen,
...
}, {
navigationOptions: {
header: {
visible: false,
},
},
});
提示:你仍然可以在子代導航screen上定制navigationOptions
.-例如,上面的ProfileScreen
.從screen獲得的navigationOptions
會和從navigator來的配置按照鍵-鍵的方式融合在一起.無論在什么而時間,navigator和screen定義相同的配置(例如:header
),screen會優先使用.因此,當ProfileScreen
激活的時候,你可以使header再次可見.
擴展默認配置:為了使用screen特定的properties擴展默認配置,而不是重寫它,你可以像下面一樣配置選項:
class ProfileScreen extends React.Component {
static navigationOptions = {
header: (navigation, defaultHeader) => ({
...defaultHeader,
visible: true,
}),
}
...
}
傳遞到函數的第二個參數作為在navigator中定義的header
的默認值.
Tab Navigation Options
class TabScreen extends React.Component {
static navigationOptions = {
tabBar: ({ state }) => ({
label: 'Tab Label',
icon: ({ tintColor }) => (
<Image
source={require('./tab-icon.png')}
style={[styles.icon, {tintColor: tintColor}]}
/>
),
visible: true
}),
};
};
-
label
-可以是字符串或者是React組件 -
icon
-函數返回icon組件 -
visible
-true或者false,顯示或者隱藏tab bar,默認是true
Custom Navigation
一個navigator是任何包含router的React組件.這里是一個基本navigator,使用router的API去獲得激活組件來渲染
class MyNavigator extends React.Component {
static router = MyRouter;
render() {
const { state, dispatch } = this.props.navigation;
const { routes, index } = state;
// Figure out what to render based on the navigation state and the router:
const Component = MyRouter.getComponentForState(state);
// The state of the active child screen can be found at routes[index]
let childNavigation = { dispatch, state: routes[index] };
// If we want, we can also tinker with the dispatch function here, to limit
// or augment our children's actions
// Assuming our children want the convenience of calling .navigate() and so on,
// we should call addNavigationHelpers to augment our navigation prop:
childNavigation = addNavigationHelpers(childNavigation);
return <Component navigation={childNavigation} />;
}
}
Navigation Prop
navigation prop傳遞給navigator的僅僅包含state
和dispatch
,這是當前的navigator的state,但是還有一個事件頻道用來發送action request.
所有的navigators都是受控組件:他們總是顯示根據props.navigation.state
來顯示,他們要改變state,唯一的辦法是發送actions到props.navigation.dispatch
.
Navigators可以通過定制他們的router來改變父navigators的行為.例如,當action應該從router.getStateForAction
返回null來阻止其運行的時候.或者一個navigator可以為了定制URI的操作而改寫router.getActionForPathParams
,為了輸出相對navigation action以及操作router.getStateForAction
的action.
Navigation State
傳遞到props.navigation.state
的navigation state有下面的結構:
{
index: 1, // identifies which route in the routes array is active
routes: [
{
// Each route needs a name, which routers will use to associate each route
// with a react component
routeName: 'MyRouteName',
// A unique id for this route, used to keep order in the routes array:
key: 'myroute-123',
// Routes can have any additional data. The included routers have `params`
...customRouteData,
},
...moreRoutes,
]
}
Navigation Dispatchers
navigator可以dispatch navigation actions,例如Go to URI,Go back.
如果action被成功操作了,dispatcher將會返回true,否則就是false
構建定制navigators的API
為了幫助開發者實施定制navigators,React Navigation提供了下面的工具
createNavigator
這個工具使用標準方法把router和navigation view合并在一起.
const MyApp = createNavigator(MyRouter)(MyView);
幕后所做的是:
const MyApp = ({ navigation }) => (
<MyView router={MyRouter} navigation={navigation} />
);
MyApp.router = MyRouter;
addNavigationHelpers
接收一個擁有state
和dispatch
的純navigator的prop,傳遞的參數是在screen navigation prop中的各種函數,例如navigation.navigate()
和navigation.goBack()
.這些函數是簡單的助手函數幫助創建action并且發送到dispatch
.
createNavigationContainer
如果你想讓你的navigator作為頂層組件使用(沒有navigation prop傳入),你可以使用createNavigationContainer
.當缺少navigtion prop的時候,這個工具使你的navigator看起來像一個頂層的導航組件.它將管理app的state,和app級別的導航特性整合在一起,例如操作進出的鏈接和android的返回按鈕行為.