Skip to main content
Version: 7.x

定制路由

路由对象提供了各种辅助程序方法来处理状态和操作,一个用于更新状态的 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 - 返回导航器初始状态的函数。接收具有 routeNamesrouteParamList 属性的选项对象。

    ¥getInitialState - Function which returns the initial state for the navigator. Receives an options object with routeNames and routeParamList properties.

  • getRehydratedState - 从给定的部分状态重新水化完整 导航状态 的功能。接收部分状态对象和具有 routeNamesrouteParamList 属性的选项对象。

    ¥getRehydratedState - Function which rehydrates the full navigation state from a given partial state. Receives a partial state object and an options object with routeNames and routeParamList properties.

  • getStateForRouteNamesChange - 获取当前状态和更新的路由名称列表并返回新状态的函数。接收状态对象和具有 routeNamesrouteParamList 属性的选项对象。

    ¥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 with routeNames and routeParamList properties.

  • getStateForAction - 函数获取当前状态和操作以及具有 routeNamesrouteParamList 属性的选项对象,并返回新状态。如果该操作无法处理,则应返回 null

    ¥getStateForAction - function which takes the current state and action along with an options object with routeNames and routeParamList properties, and returns a new state. If the action cannot be handled, it should return null.

  • 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 as NAVIGATE can change focus in the parent.

  • actionCreators - 包含动作创建者列表的可选对象,例如 pushpop 等。这些将用于向 navigation 对象添加辅助方法以分派这些动作。

    ¥actionCreators - Optional object containing a list of action creators, such as push, pop etc. These will be used to add helper methods to the navigation 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

有时你可能想要阻止某些导航活动,具体取决于你的路由。假设,如果 isEditingtrue,你希望阻止推送新屏幕:

¥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.