定制路由
路由对象提供了各种辅助程序方法来处理状态和操作,一个用于更新状态的 reducer 以及一些操作创建器。
¥The router object provides various helper methods to deal with the state and actions, a reducer to update the state as well as some action creators.
路由负责处理通过调用导航对象上的方法分派的操作。如果路由无法处理某个操作,它可以返回 null
,这会将操作传播到其他路由,直到它得到处理。
¥The router is responsible for handling actions dispatched by calling methods on the navigation object. If the router cannot handle an action, it can return null
, which would propagate the action to other routers until it's handled.
你可以通过构建具有以下功能的对象来制作自己的路由:
¥You can make your own router by building an object with the following functions:
-
type
- 表示路由类型的字符串,例如'stack'
、'tab'
、'drawer'
等¥
type
- String representing the type of the router, e.g.'stack'
,'tab'
,'drawer'
etc. -
getInitialState
- 返回导航器初始状态的函数。接收具有routeNames
和routeParamList
属性的选项对象。¥
getInitialState
- Function which returns the initial state for the navigator. Receives an options object withrouteNames
androuteParamList
properties. -
getRehydratedState
- 从给定的部分状态重新水化完整 导航状态 的功能。接收部分状态对象和具有routeNames
和routeParamList
属性的选项对象。¥
getRehydratedState
- Function which rehydrates the full navigation state from a given partial state. Receives a partial state object and an options object withrouteNames
androuteParamList
properties. -
getStateForRouteNamesChange
- 获取当前状态和更新的路由名称列表并返回新状态的函数。接收状态对象和具有routeNames
和routeParamList
属性的选项对象。¥
getStateForRouteNamesChange
- Function which takes the current state and updated list of route names, and returns a new state. Receives the state object and an options object withrouteNames
androuteParamList
properties. -
getStateForAction
- 函数获取当前状态和操作以及具有routeNames
和routeParamList
属性的选项对象,并返回新状态。如果该操作无法处理,则应返回null
。¥
getStateForAction
- function which takes the current state and action along with an options object withrouteNames
androuteParamList
properties, and returns a new state. If the action cannot be handled, it should returnnull
. -
getStateForRouteFocus
- 获取路由的当前状态和键,并返回以该路由为焦点的新状态的函数。¥
getStateForRouteFocus
- Function which takes the current state and key of a route, and returns a new state with that route focused. -
shouldActionChangeFocus
- 确定操作是否也应更改父导航器中的焦点的函数。某些操作(例如NAVIGATE
)可以更改父项中的焦点。¥
shouldActionChangeFocus
- Function which determines whether the action should also change focus in parent navigator. Some actions such asNAVIGATE
can change focus in the parent. -
actionCreators
- 包含动作创建者列表的可选对象,例如push
、pop
等。这些将用于向navigation
对象添加辅助方法以分派这些动作。¥
actionCreators
- Optional object containing a list of action creators, such aspush
,pop
etc. These will be used to add helper methods to thenavigation
object to dispatch those actions.
示例:
¥Example:
const router = {
type: 'tab',
getInitialState({ routeNames, routeParamList }) {
const index =
options.initialRouteName === undefined
? 0
: routeNames.indexOf(options.initialRouteName);
return {
stale: false,
type: 'tab',
key: shortid(),
index,
routeNames,
routes: routeNames.map(name => ({
name,
key: name,
params: routeParamList[name],
})),
};
},
getRehydratedState(partialState, { routeNames, routeParamList }) {
const state = partialState;
if (state.stale === false) {
return state as NavigationState;
}
const routes = state.routes
.filter(route => routeNames.includes(route.name))
.map(
route =>
({
...route,
key: route.key || `${route.name}-${shortid()}`,
params:
routeParamList[route.name] !== undefined
? {
...routeParamList[route.name],
...route.params,
}
: route.params,
} as Route<string>)
);
return {
stale: false,
type: 'tab',
key: shortid(),
index:
typeof state.index === 'number' && state.index < routes.length
? state.index
: 0,
routeNames,
routes,
};
},
getStateForRouteNamesChange(state, { routeNames }) {
const routes = state.routes.filter(route =>
routeNames.includes(route.name)
);
return {
...state,
routeNames,
routes,
index: Math.min(state.index, routes.length - 1),
};
},
getStateForRouteFocus(state, key) {
const index = state.routes.findIndex(r => r.key === key);
if (index === -1 || index === state.index) {
return state;
}
return { ...state, index };
},
getStateForAction(state, action) {
switch (action.type) {
case 'NAVIGATE': {
const index = state.routes.findIndex(
route => route.name === action.payload.name
);
if (index === -1) {
return null;
}
return { ...state, index };
}
default:
return BaseRouter.getStateForAction(state, action);
}
},
shouldActionChangeFocus() {
return false;
},
};
const SimpleRouter = () => router;
export default SimpleRouter;
内置路由
¥Built-In Routers
该库附带了一些标准路由:
¥The library ships with a few standard routers:
-
StackRouter
-
TabRouter
-
DrawerRouter
定制路由
¥Customizing Routers
你可以重用路由并根据需要覆盖路由功能,例如自定义现有操作的处理方式、添加其他操作等。
¥You can reuse a router and override the router functions as per your needs, such as customizing how existing actions are handled, adding additional actions etc.
有关如何在现有导航器中使用自定义路由覆盖路由的详细信息,请参阅 自定义导航器。
¥See custom navigators for details on how to override the router with a custom router in an existing navigator.
自定义导航操作
¥Custom Navigation Actions
假设你要添加自定义操作来清除历史记录:
¥Let's say you want to add a custom action to clear the history:
import { TabRouter } from '@react-navigation/native';
const MyTabRouter = (options) => {
const router = TabRouter(options);
return {
...router,
getStateForAction(state, action, options) {
switch (action.type) {
case 'CLEAR_HISTORY':
return {
...state,
routeKeyHistory: [],
};
default:
return router.getStateForAction(state, action, options);
}
},
actionCreators: {
...router.actionCreators,
clearHistory() {
return { type: 'CLEAR_HISTORY' };
},
},
};
};
你可以使用 将函数传递给 dispatch
代替编写自定义路由来处理自定义操作。它更干净,推荐代替覆盖路由。
¥Instead of writing a custom router to handle custom actions, you can pass a function to dispatch
instead. It's cleaner and recommended instead of overriding routers.
阻止导航操作
¥Blocking Navigation Actions
有时你可能想要阻止某些导航活动,具体取决于你的路由。假设,如果 isEditing
是 true
,你希望阻止推送新屏幕:
¥Sometimes you may want to prevent some navigation activity, depending on your route. Let's say, you want to prevent pushing a new screen if isEditing
is true
:
import { StackRouter } from '@react-navigation/native';
const MyStackRouter = (options) => {
const router = StackRouter(options);
return {
...router,
getStateForAction(state, action, options) {
const result = router.getStateForAction(state, action, options);
if (
result != null &&
result.index > state.index &&
state.routes[state.index].params?.isEditing
) {
// Returning the current state means that the action has been handled, but we don't have a new state
return state;
}
return result;
},
};
};
如果你想防止返回,推荐的方法是使用 usePreventRemove
钩。
¥If you want to prevent going back, the recommended approach is to use the usePreventRemove
hook.