title: 翻譯|React-navigation導(dǎo)航系統(tǒng)(5)-Router
date: 2017-03-30 09:57:00
categories: 翻譯
tags: React-Native
Routers
Router定義一個(gè)組件的navigation state,允許開(kāi)發(fā)者定義路徑和可以操作的actions.
內(nèi)建的Routers
- StackRouter
- TabRouter
使用Routers
為了手動(dòng)定制一個(gè)navigator,在組件里可以放一個(gè)靜態(tài)的router
.(使用內(nèi)建的組件快速的定制一個(gè)navigator,使用Navigator Factory更容易實(shí)現(xiàn)).
class MyNavigator extends React.Component {
static router = StackRouter(routes, config);
...
}
現(xiàn)在你可以把這個(gè)組件作為另一個(gè)navigator的screen
對(duì)待,MyNavigator
的導(dǎo)航邏輯在StackRouter
中定義.
定制化Router
看看[定制Router API 部分](https://reactnavigation.org/docs/routers/api)
學(xué)習(xí)StackRouter
和TabRouter
的API.
只要你愿意也可以重寫(xiě)router的函數(shù).
定制Navigation的Actions
為了重寫(xiě)navigation的行為,你可以在getStateForAction
中重寫(xiě)navigation state的邏輯,從而手動(dòng)處理routes
和index
.
const MyApp = StackNavigator({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
}, {
initialRouteName: 'Home',
})
MyApp.router = {
...MyApp.router,
getStateForAction(action, state) {
if (state && action.type === 'PushTwoProfiles') {
const routes = [
...state.routes,
{key: 'A', routeName: 'Profile', params: { name: action.name1 }},
{key: 'B', routeName: 'Profile', params: { name: action.name2 }},
];
return {
...state,
routes,
index: routes.length - 1,
};
}
return MyApp.router.getStateForAction(action, state);
},
};
阻止某些Navigation的Actions
有時(shí)候根據(jù)你的route,需要阻止某些navigation的活動(dòng)
const MyStackRouter = StackRouter({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
}, {
initialRouteName: 'Home',
})
const MyAppRouter = {
...MyStackRouter,
getStateForAction(action, state) {
if (
state &&
action.type === NavigationActions.BACK &&
state.routes[state.index].params.isEditing
) {
// Returning null from getStateForAction means that the action
// has been handled/blocked, but there is not a new state
return null;
}
return MyStackRouter.getStateForAction(action, state);
},
};
操作定制URIs
或許你的app有一個(gè)獨(dú)特的URI,內(nèi)建的routers處理不了.你可以通過(guò)getActionForPathAndParams
來(lái)擴(kuò)展router.
import { NavigationActions } from 'react-navigation'
const MyApp = StackNavigator({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
}, {
initialRouteName: 'Home',
})
const previousGetActionForPathAndParams = MyApp.router.getActionForPathAndParams
Object.assign(MyApp.router, {
getActionForPathAndParams(path, params) {
if (
path === 'my/custom/path' &&
params.magic === 'yes'
) {
// returns a profile navigate action for /my/custom/path?magic=yes
return NavigationActions.navigate({
routeName: 'Profile',
action: NavigationActions.navigate({
// This child action will get passed to the child router
// ProfileScreen.router.getStateForAction to get the child
// navigation state.
routeName: 'Friends',
}),
});
}
return previousGetActionForPathAndParams(path, params);
},
};
定制Router API
你可以童工下面的函數(shù)來(lái)構(gòu)建自己的router對(duì)象,
const MyRouter = {
getStateForAction: (action, state) => ({}),
getActionForPathAndParams: (path, params) => null,
getPathAndParamsForState: (state) => null,
getComponentForState: (state) => MyScreen,
getComponentForRouteName: (routeName) => MyScreen,
};
// Now, you can make a navigator by putting the router on it:
class MyNavigator extends React.Component {
static router = MyRouter;
render() {
...
}
}
getStateForAction(action,state)
根據(jù)給定的action來(lái)定義返回的navigation sate.當(dāng)一個(gè)action通過(guò)props.navigation.dispatch()
傳遞,或者任何其他的助手函數(shù)被調(diào)用,例如navigation.navitate()
的時(shí)候,這個(gè)函數(shù)將會(huì)運(yùn)行.
通常這個(gè)函數(shù)將會(huì)以下面的形式返回navitaion state.
{
index: 1, // identifies which route in the routes array is active
routes: [
{
// Each route needs a name to identify the type.
routeName: 'MyRouteName',
// A unique identifier for this route in the routes array:
key: 'myroute-123',
// (used to specify the re-ordering of routes)
// Routes can have any data, as long as key and routeName are correct
...randomRouteData,
},
...moreRoutes,
]
}
如果router已經(jīng)在外部處理了acion,或者想不改變?nèi)魏蔚膎avigation state就消化它,這個(gè)函數(shù)就返回null
.
getComponentForRouterName(routeName)
為給定的route name返回子組件或者navigator.
像這樣聲明一個(gè)routergetStateForAction
輸出的state.
{
index: 1,
routes: [
{ key: 'A', routeName: 'Foo' },
{ key: 'B', routeName: 'Bar' },
],
}
基于state中的額routeName,router將會(huì)調(diào)用router.getComponentForRouteName('Foo')
或router.getComponentForRouteName('Bar')
來(lái)返回對(duì)應(yīng)的有效組件.
getComponentForState(state)
從深度嵌套navigation state返回激活的組件
getActionForPathAndParams
返回一個(gè)可選配置的navigation action,在用戶(hù)導(dǎo)航到這個(gè)路徑并且有可選的查詢(xún)參數(shù)的時(shí)候使用這個(gè)action.
getPathAndParamsForState
用戶(hù)在app中返回同一個(gè)URL鏈接的點(diǎn)時(shí),這個(gè)函數(shù)返回路徑和參數(shù).
從這個(gè)函數(shù)返回的路徑和參數(shù)應(yīng)該是從一個(gè)action獲得的,這個(gè)action是重傳進(jìn)入router的getActionForPathAndParams
的.這個(gè)action一旦通過(guò)getStateForAction
傳遞,會(huì)給你返回形似的state.
getScreenConfig
這個(gè)函數(shù)從一個(gè)route獲取navigation的可選項(xiàng).必須要提供screen的當(dāng)前navigation prop和被返回的選項(xiàng)的名字.
-
navigation
-這是screen將會(huì)使用的navigation prop,對(duì)應(yīng)在screen的route和state.Dispatch將會(huì)根據(jù)screen的上下文來(lái)觸發(fā)actions. -
optionName
-被獲取的選項(xiàng)的名字,例如’title’
在實(shí)例的視圖內(nèi),或許你需要遠(yuǎn)程獲取配置的標(biāo)題
// First, prepare a navigation prop for your child, or re-use one if already available.
const childNavigation = addNavigationHelpers({
// In this case we use navigation.state.index because we want the title for the active route.
state: navigation.state.routes[navigation.state.index],
dispatch: navigation.dispatch,
})
const screenTitle = this.props.router.getScreenConfig(childNavigation, 'title');
StackRouter
管理navigation堆棧的邏輯,包括入棧,出棧,操作路徑解析創(chuàng)建深層次的堆棧.
讓我們看看簡(jiǎn)單的stack router
const MyApp = StackRouter({
Home: { screen: HomeScreen },
Profile: { screen: ProfileScreen },
}, {
initialRouteName: 'Home',
})
RouteConfig
最簡(jiǎn)單的stack router期待的參數(shù)是一個(gè)config對(duì)象,這里是示例配置
const MyApp = StackRouter({ // This is the RouteConfig:
Home: {
screen: HomeScreen,
path: '',
},
Profile: {
screen: ProfileScreen,
path: 'profile/:name',
},
Settings {
// This can be handy to lazily require a screen:
getScreen: () => require('Settings').default,
// Note: Child navigators cannot be configured using getScreen because
// the router will not be accessible. Navigators must be configured
// using `screen: MyNavigator`
path: 'settings',
},
});
每一個(gè)在config中的條目有如下內(nèi)容
-
path
-設(shè)定條目的路徑和參數(shù)可以在stack中被解析 -
screen
-設(shè)定screen組件或者子navigator -
getScreen
-為screen組件設(shè)定惰性加載的設(shè)定
StackConfig
配置的選項(xiàng)也被傳遞進(jìn)入stack router.
-
initalRouteName
-stack首次加載的默認(rèn)路由的routeName -
initialRouteParams
-初始化route的默認(rèn)參數(shù) -
paths
-提供routeName到path配置的映射,將會(huì)重寫(xiě)routeConfigs里的path設(shè)置
Supported Actions
stack router可以對(duì)下面的導(dǎo)航actions作為響應(yīng).如果有可能,router將會(huì)代理到子代router的action操作.
- Navigate-如果routeName和router的routerConfigs其中之一匹配,將會(huì)push一個(gè)新的route到堆棧.
- Back-返回(props)
- Reset-清除堆棧,提供一個(gè)新的actions創(chuàng)建新的navigation state
- SetParams-screen dispatch一個(gè)action去改變當(dāng)前route的參數(shù)
TabRouter
管理應(yīng)用中的一套tabs,處理tabs之間的跳轉(zhuǎn),處理back鍵的操作返回到初始化的tab.
看看簡(jiǎn)單的tabs router
const MyApp = TabRouter({
Home: { screen: HomeScreen },
Settings: { screen: SettingsScreen },
}, {
initialRouteName: 'Home',
})
RouteConfig
tabs router有為每一個(gè)tab的routeConfig
const MyApp = TabRouter({ // This is the RouteConfig:
Home: {
screen: HomeScreen,
path: 'main',
},
Settings: {
// This can be handy to lazily require a tab:
getScreen: () => require('./SettingsScreen').default,
// Note: Child navigators cannot be configured using getScreen because
// the router will not be accessible. Navigators must be configured
// using `screen: MyNavigator`
path: 'settings',
},
});
config中的每一個(gè)config可能有
-
config
-每一個(gè)tab的path -
screen
-定制screen組件或者子代navigator -
getScreen
-為一個(gè)screen組件設(shè)定惰性加載的設(shè)置(navigator沒(méi)有這樣的配置)
Tab Router Config
被傳遞到router的可配置選項(xiàng)
-
initialRouteName
-首次加載的tab的routeName -
order
-tabs的順序 -
path
-提供routeName到path config的映射,映射重寫(xiě)routeConfig中的path設(shè)定 -
backBehavior
-點(diǎn)擊back按鈕應(yīng)該返回到初始化的tab嗎?如果是的話(huà),設(shè)置initialRoute
,否則就是none
,默認(rèn)到initialRoute
的行為.
Support Actions
tabs router會(huì)對(duì)下面的navigation actions做出響應(yīng).如果有可能,router將代理到子代router的action.
- Navigate-如果和tab的routeName匹配,就會(huì)跳轉(zhuǎn)到對(duì)應(yīng)的tab
- Back-如果不是第一個(gè)默認(rèn)的tab,就跳轉(zhuǎn)到第一個(gè)tab
- SetParams-screen dispatch一個(gè)Action來(lái)改變當(dāng)前route的state