Skip to main content
Version: 7.x

配置链接

在本指南中,我们将配置 React Navigation 来处理外部链接。如果你想要:

¥In this guide, we will configure React Navigation to handle external links. This is necessary if you want to:

  1. 处理 Android 和 iOS 上的 React Native 应用中的深层链接

    ¥Handle deep links in React Native apps on Android and iOS

  2. 在网络上使用时启用浏览器中的 URL 集成

    ¥Enable URL integration in browser when using on web

  3. 使用 <Link />useLinkTo 使用路径进行导航。

    ¥Use <Link /> or useLinkTo to navigate using paths.

在继续之前,请确保你的应用中有 配置的深层链接。如果你有 Android 或 iOS 应用,请记住指定 prefixes 选项。

¥Make sure that you have configured deep links in your app before proceeding. If you have an Android or iOS app, remember to specify the prefixes option.

Navigation 组件接受 linking prop,这使得处理传入链接更加容易:

¥The Navigation component accepts a linking prop that makes it easier to handle incoming links:

import { createStaticNavigation } from '@react-navigation/native';

const linking = {
enabled: 'auto' /* Automatically generate paths for all screens */,
prefixes: [
/* your linking prefixes */
],
};

function App() {
return (
<Navigation
linking={linking}
fallback={<Text>Loading...</Text>}
/>
);
}

const Navigation = createStaticNavigation(RootStack);

当你指定 linking 属性时,React Navigation 将自动处理传入链接。在 Android 和 iOS 上,它将使用 React Native 的 Linking 模块 来处理传入链接,无论是在使用链接打开应用时,还是在打开应用时收到新链接时。在 Web 上,它将使用 历史 API 将 URL 与浏览器同步。

¥When you specify the linking prop, React Navigation will handle incoming links automatically. On Android and iOS, it'll use React Native's Linking module to handle incoming links, both when the app was opened with the link, and when new links are received when the app is open. On the Web, it'll use the History API to sync the URL with the browser.

警告

目前似乎存在 bug (facebook/react-native#25675),导致它在 Android 上永远无法解决。我们添加了超时以避免永远卡住,但这意味着在某些情况下可能无法处理链接。

¥Currently there seems to be bug (facebook/react-native#25675) which results in it never resolving on Android. We add a timeout to avoid getting stuck forever, but it means that the link might not be handled in some cases.

你还可以传递一个 fallback prop,该 prop 控制 React Navigation 尝试解析初始深层链接 URL 时显示的内容。

¥You can also pass a fallback prop that controls what's displayed when React Navigation is trying to resolve the initial deep link URL.

前缀

¥Prefixes

如果你配置了 通用链接安卓应用链接,则 prefixes 选项可用于指定自定义方案(例如 mychat://)以及主机名和域名(例如 https://mychat.com)。

¥The prefixes option can be used to specify custom schemes (e.g. mychat://) as well as host & domain names (e.g. https://mychat.com) if you have configured Universal Links or Android App Links.

例如:

¥For example:

const linking = {
prefixes: ['mychat://', 'https://mychat.com'],
};

请注意,Web 上不支持 prefixes 选项。主机名和域名将根据浏览器中的网站 URL 自动确定。如果你的应用仅在 Web 上运行,那么你可以从配置中省略此选项。

¥Note that the prefixes option is not supported on Web. The host & domain names will be automatically determined from the Website URL in the browser. If your app runs only on Web, then you can omit this option from the config.

多个子域​

¥Multiple subdomains​

要匹配关联域的所有子域,你可以通过前缀 * 来指定通配符。在特定域的开始之前。请注意,由于星号后面有句点,因此 *.mychat.com 的条目与 mychat.com 不匹配。要启用 *.mychat.commychat.com 的匹配,你需要为每个提供单独的前缀条目。

¥To match all subdomains of an associated domain, you can specify a wildcard by prefixing *. before the beginning of a specific domain. Note that an entry for *.mychat.com does not match mychat.com because of the period after the asterisk. To enable matching for both *.mychat.com and mychat.com, you need to provide a separate prefix entry for each.

const linking = {
prefixes: ['mychat://', 'https://mychat.com', 'https://*.mychat.com'],
};

过滤某些路径

¥Filtering certain paths

有时我们可能不想处理所有传入链接。例如,我们可能希望过滤掉用于身份验证(例如 expo-auth-session)或其他目的的链接,而不是导航到特定屏幕。

¥Sometimes we may not want to handle all incoming links. For example, we may want to filter out links meant for authentication (e.g. expo-auth-session) or other purposes instead of navigating to a specific screen.

为此,你可以使用 filter 选项:

¥To achieve this, you can use the filter option:

const linking = {
prefixes: ['mychat://', 'https://mychat.com'],
filter: (url) => !url.includes('+expo-auth-session'),
};

Web 上不支持此功能,因为我们始终需要处理页面的 URL。

¥This is not supported on Web as we always need to handle the URL of the page.

子路径下的应用

¥Apps under subpaths

如果你的应用托管在子路径下,你可以在 config 的顶层指定子路径。例如,如果你的应用托管在 https://mychat.com/app 上,你可以将 path 指定为 app

¥If your app is hosted under a subpath, you can specify the subpath at the top-level of the config. For example, if your app is hosted at https://mychat.com/app, you can specify the path as app:

const linking = {
prefixes: ['mychat://', 'https://mychat.com'],
config: {
path: 'app',

// ...
},
};

由于这不属于屏幕,因此无法在此处指定参数,例如 app/:id 将不起作用。

¥It's not possible to specify params here since this doesn't belong to a screen, e.g. app/:id won't work.

将路径映射到路由名称

¥Mapping path to route names

如果你在 linking prop 中指定 enabled: 'auto',React Navigation 将自动为所有屏幕生成路径。例如,如果导航器中有一个 Profile 屏幕,它将自动为其生成一个路径作为 profile

¥If you specify enabled: 'auto' in the linking prop, React Navigation will automatically generate paths for all screens. For example, if you have a Profile screen in the navigator, it'll automatically generate a path for it as profile.

如果你希望手动处理配置,或者想要覆盖特定屏幕的生成路径,则可以在导航器中屏幕旁边指定 linking 属性以将路径映射到屏幕。例如:

¥If you wish to handle the configuration manually, or want to override the generated path for a specific screen, you can specify linking property next to the screen in the navigator to map a path to a screen. For example:

const RootStack = createStackNavigator({
screens: {
Profile: {
screen: ProfileScreen,
linking: {
path: 'user',
},
},
Chat: {
screen: ChatScreen,
linking: {
path: 'feed/:sort',
},
},
},
});

在此示例中:

¥In this example:

  • Chat 屏幕使用参数 sort 处理 URL /feed(例如 /feed/latest - Chat 屏幕将接收带有值 latest 的参数 sort)。

    ¥Chat screen that handles the URL /feed with the param sort (e.g. /feed/latest - the Chat screen will receive a param sort with the value latest).

  • Profile 屏幕处理 URL /user

    ¥Profile screen that handles the URL /user.

类似地,当你有嵌套导航器时,你可以为导航器中的屏幕指定 linking 属性来处理嵌套屏幕的路径:

¥Similarly, when you have a nested navigator, you can specify the linking property for the screens in the navigator to handle the path for the nested screens:

const HomeTabs = createBottomTabNavigator({
screens: {
Home: {
screen: HomeScreen,
linking: {
path: 'home',
},
},
Settings: {
screen: SettingsScreen,
linking: {
path: 'settings',
},
},
},
});

const RootStack = createStackNavigator({
screens: {
HomeTabs: {
screen: HomeTabs,
},
Profile: {
screen: ProfileScreen,
linking: {
path: 'user',
},
},
Chat: {
screen: ChatScreen,
linking: {
path: 'feed/:sort',
},
},
},
});

在上面的例子中,处理以下路径格式:

¥In the above example, the following path formats are handled:

  • /home 导航到 HomeTabs -> Home 屏幕

    ¥/home navigates to the HomeTabs -> Home screen

  • /settings 导航到 HomeTabs -> Settings 屏幕

    ¥/settings navigates to the HomeTabs -> Settings screen

  • /user 导航到 Profile 屏幕

    ¥/user navigates to the Profile screen

  • /feed/:sort 使用参数 sort 导航到 Chat 屏幕

    ¥/feed/:sort navigates to the Chat screen with the param sort

自动路径生成如何工作?

¥How does automatic path generation work?

使用 enabled: 'auto' 自动路径生成时,适用以下规则:

¥When using automatic path generation with enabled: 'auto', the following rules are applied:

  • 具有显式 linking 属性的屏幕不用于路径生成,将按原样添加。

    ¥Screens with an explicit linking property are not used for path generation and will be added as-is.

  • 屏幕名称将从 PascalCase 转换为 kebab-case 以用作路径(例如 NewsFeed -> news-feed)。

    ¥Screen names will be converted from PascalCase to kebab-case to use as the path (e.g. NewsFeed -> news-feed).

  • 除非屏幕具有明确的空路径(path: '')用作主页,否则遇到的第一个叶屏幕将用作主页。

    ¥Unless a screen has explicit empty path (path: '') to use for the homepage, the first leaf screen encountered will be used as the homepage.

  • 路径生成仅处理叶屏幕,即不为包含嵌套导航器的屏幕生成路径。仍然可以使用显式 linking 属性为它们指定路径。

    ¥Path generation only handles leaf screens, i.e. no path is generated for screens containing nested navigators. It's still possible to specify a path for them with an explicit linking property.

假设我们有以下导航结构:

¥Let's say we have the following navigation structure:

const HomeTabs = createBottomTabNavigator({
screens: {
Home: {
screen: HomeScreen,
},
Settings: {
screen: SettingsScreen,
},
},
});

const RootStack = createStackNavigator({
screens: {
HomeTabs: {
screen: HomeTabs,
},
Profile: {
screen: ProfileScreen,
},
Chat: {
screen: ChatScreen,
},
},
});

使用自动路径生成,将生成以下路径:

¥With automatic path generation, the following paths will be generated:

  • / 导航到 HomeTabs -> Home 屏幕

    ¥/ navigates to the HomeTabs -> Home screen

  • /settings 导航到 HomeTabs -> Settings 屏幕

    ¥/settings navigates to the HomeTabs -> Settings screen

  • /profile 导航到 Profile 屏幕

    ¥/profile navigates to the Profile screen

  • /chat 导航到 Chat 屏幕

    ¥/chat navigates to the Chat screen

如果 URL 包含查询字符串,它将作为参数传递给屏幕。例如,URL /profile?user=jane 将把 user 参数传递给 Profile 屏幕。

¥If the URL contains a query string, it'll be passed as params to the screen. For example, the URL /profile?user=jane will pass the user param to the Profile screen.

How it works

链接通过使用提供的配置将 URL 转换为有效的 导航状态 并反之亦然。例如,路径 /rooms/chat?user=jane 可以转换为如下状态对象:

¥The linking works by translating the URL to a valid navigation state and vice versa using the configuration provided. For example, the path /rooms/chat?user=jane may be translated to a state object like this:

const state = {
routes: [
{
name: 'rooms',
state: {
routes: [
{
name: 'chat',
params: { user: 'jane' },
},
],
},
},
],
};

例如,你可能希望将路径 /feed/latest 解析为:

¥For example, you might want to parse the path /feed/latest to something like:

const state = {
routes: [
{
name: 'Chat',
params: {
sort: 'latest',
},
},
];
}

有关状态对象如何构造的更多详细信息,请参阅 导航状态参考

¥See Navigation State reference for more details on how the state object is structured.

传递参数

¥Passing params

一个常见的用例是将参数传递到屏幕以传递一些数据。例如,你可能希望 Profile 屏幕有一个 id 参数来了解它是哪个用户的个人资料。处理深层链接时,可以通过 URL 将参数传递到屏幕。

¥A common use case is to pass params to a screen to pass some data. For example, you may want the Profile screen to have an id param to know which user's profile it is. It's possible to pass params to a screen through a URL when handling deep links.

默认情况下,解析查询参数以获取屏幕的参数。例如,在上面的示例中,URL /user?id=jane 会将 id 参数传递到 Profile 屏幕。

¥By default, query params are parsed to get the params for a screen. For example, with the above example, the URL /user?id=jane will pass the id param to the Profile screen.

你还可以自定义如何从 URL 解析参数。假设你希望 URL 看起来像 /user/jane,其中 id 参数是 jane,而不是在查询参数中包含 id。你可以通过为 path 指定 user/:id 来完成此操作。当路径段以 : 开头时,它将被视为参数。例如,URL /user/jane 将解析为 Profile 屏幕,其中字符串 jane 作为 id 参数的值,并将在 Profile 屏幕中的 route.params.id 中可用。

¥You can also customize how the params are parsed from the URL. Let's say you want the URL to look like /user/jane where the id param is jane instead of having the id in query params. You can do this by specifying user/:id for the path. When the path segment starts with :, it'll be treated as a param. For example, the URL /user/jane would resolve to Profile screen with the string jane as a value of the id param and will be available in route.params.id in Profile screen.

默认情况下,所有参数都被视为字符串。你还可以自定义如何解析它们,方法是在 parse 属性中指定一个函数来解析参数,并在 stringify 属性中指定一个函数将其转换回字符串。

¥By default, all params are treated as strings. You can also customize how to parse them by specifying a function in the parse property to parse the param, and a function in the stringify property to convert it back to a string.

如果你想解析 /user/@jane/settings 以生成参数 { id: 'jane' section: 'settings' },你可以使 Profile 的配置如下所示:

¥If you wanted to resolve /user/@jane/settings to result in the params { id: 'jane' section: 'settings' }, you could make Profile's config to look like this:

const RootStack = createStackNavigator({
screens: {
Profile: {
screen: ProfileScreen,
linking: {
path: 'user/:id/:section',
parse: {
id: (id) => id.replace(/^@/, ''),
},
stringify: {
id: (id) => `@${id}`,
},
},
},
},
});
Result Navigation State

通过此配置,路径 /user/@jane/settings 将解析为以下状态对象:

¥With this configuration, the path /user/@jane/settings will resolve to the following state object:

const state = {
routes: [
{
name: 'Profile',
params: { id: 'jane', section: 'settings' },
},
],
};

将参数标记为可选

¥Marking params as optional

有时,根据某些条件,参数可能会或可能不会出现在 URL 中。例如,在上述场景中,你可能并不总是在 URL 中包含部分参数,即 /user/jane/settings/user/jane 都应转到 Profile 屏幕,但 section 参数(在本例中值为 settings)可能会或可能不会展示。

¥Sometimes a param may or may not be present in the URL depending on certain conditions. For example, in the above scenario, you may not always have the section parameter in the URL, i.e. both /user/jane/settings and /user/jane should go to the Profile screen, but the section param (with the value settings in this case) may or may not be present.

在这种情况下,你需要将 section 参数标记为可选。你可以通过在参数名称后添加 ? 后缀来实现:

¥In this case, you would need to mark the section param as optional. You can do it by adding the ? suffix after the param name:

const RootStack = createStackNavigator({
screens: {
Profile: {
screen: ProfileScreen,
linking: {
path: 'user/:id/:section?',
parse: {
id: (id) => `user-${id}`,
},
stringify: {
id: (id) => id.replace(/^user-/, ''),
},
},
},
},
});
Result Navigation State

通过此配置,路径 /user/jane 将解析为以下状态对象:

¥With this configuration, the path /user/jane will resolve to the following state object:

const state = {
routes: [
{
name: 'Profile',
params: { id: 'user-jane' },
},
],
};

如果 URL 包含 section 参数(例如 /user/jane/settings),则将导致具有相同配置的以下内容:

¥If the URL contains a section param (e.g. /user/jane/settings), this will result in the following with the same config:

const state = {
routes: [
{
name: 'Profile',
params: { id: 'user-jane', section: 'settings' },
},
],
};

处理不匹配的路由或 404

¥Handling unmatched routes or 404

如果你的应用使用无效 URL 打开,大多数时候你希望显示包含一些信息的错误页面。在网络上,这通常称为 404 - 或页面未找到错误。

¥If your app is opened with an invalid URL, most of the times you'd want to show an error page with some information. On the web, this is commonly known as 404 - or page not found error.

为了解决这个问题,你需要定义一个包罗万象的路由,如果没有其他路由与该路径匹配,则将渲染该路由。你可以通过为路径匹配模式指定 * 来实现:

¥To handle this, you'll need to define a catch-all route that will be rendered if no other routes match the path. You can do it by specifying * for the path matching pattern:

const HomeTabs = createBottomTabNavigator({
screens: {
Feed: {
screen: FeedScreen,
},
Profile: {
screen: HomeScreen,
linking: {
path: 'users/:id',
},
},
Settings: {
screen: SettingsScreen,
linking: {
path: 'settings',
},
},
},
});

const RootStack = createStackNavigator({
screens: {
Home: {
screen: HomeTabs,
},
NotFound: {
screen: NotFoundScreen,
linking: {
path: '*',
},
},
},
});

在这里,我们定义了一条名为 NotFound 的路由,并将其设置为匹配 *(即所有内容)。如果路径与 user/:idsettings 不匹配,则将通过此路由进行匹配。

¥Here, we have defined a route named NotFound and set it to match * aka everything. If the path didn't match user/:id or settings, it'll be matched by this route.

Result Navigation State

使用此配置,像 /library/settings/notification 这样的路径将解析为以下状态对象:

¥With this configuration, a path like /library or /settings/notification will resolve to the following state object:

const state = {
routes: [{ name: 'NotFound' }],
};

你甚至可以更具体,例如,如果你想为 /settings 下的无效路径显示不同的屏幕,你可以在 Settings 下指定这样的模式:

¥You can even go more specific, for example, say if you want to show a different screen for invalid paths under /settings, you can specify such a pattern under Settings:

const SettingsStack = createStackNavigator({
screens: {
UserSettings: {
screen: UserSettingsScreen,
linking: {
path: 'user-settings',
},
},
InvalidSettings: {
screen: InvalidSettingsScreen,
linking: {
path: '*',
},
},
},
});

const HomeTabs = createBottomTabNavigator({
screens: {
Feed: {
screen: FeedScreen,
},
Profile: {
screen: HomeScreen,
linking: {
path: 'users/:id',
},
},
Settings: {
screen: SettingsStack,
},
},
});

const RootStack = createStackNavigator({
screens: {
Home: {
screen: HomeTabs,
},
NotFound: {
screen: NotFoundScreen,
linking: {
path: '*',
},
},
},
});
Result Navigation State

通过此配置,路径 /settings/notification 将解析为以下状态对象:

¥With this configuration, the path /settings/notification will resolve to the following state object:

const state = {
routes: [
{
name: 'Home',
state: {
index: 1,
routes: [
{ name: 'Feed' },
{
name: 'Settings',
state: {
routes: [
{ name: 'InvalidSettings', path: '/settings/notification' },
],
},
},
],
},
},
],
};

传递到 NotFound 屏幕的 route 将包含 path 属性,该属性对应于打开页面的路径。如果需要,你可以使用此属性来自定义此屏幕中显示的内容,例如在 WebView 中加载页面:

¥The route passed to the NotFound screen will contain a path property which corresponds to the path that opened the page. If you need, you can use this property to customize what's shown in this screen, e.g. load the page in a WebView:

function NotFoundScreen({ route }) {
if (route.path) {
return <WebView source={{ uri: `https://mywebsite.com/${route.path}` }} />;
}

return <Text>This screen doesn't exist!</Text>;
}

在进行服务器渲染时,你还希望返回 404 错误的正确状态代码。有关如何处理它的指南,请参阅 服务器渲染文档

¥When doing server rendering, you'd also want to return correct status code for 404 errors. See server rendering docs for a guide on how to handle it.

渲染初始路由

¥Rendering an initial route

有时你希望确保某个屏幕始终作为导航器状态中的第一个屏幕出现。你可以使用 initialRouteName 属性指定用于初始屏幕的屏幕。

¥Sometimes you want to ensure that a certain screen will always be present as the first screen in the navigator's state. You can use the initialRouteName property to specify the screen to use for the initial screen.

在上面的示例中,如果你希望 Feed 屏幕成为 Home 下导航器中的初始路由,你的配置将如下所示:

¥In the above example, if you want the Feed screen to be the initial route in the navigator under Home, your config will look like this:

const HomeTabs = createBottomTabNavigator({
screens: {
Feed: {
screen: FeedScreen,
},
Profile: {
screen: HomeScreen,
linking: {
path: 'users/:id',
},
},
Settings: {
screen: SettingsScreen,
linking: {
path: 'settings',
},
},
},
});

const RootStack = createStackNavigator({
screens: {
Home: {
screen: HomeTabs,
linking: {
initialRouteName: 'Feed',
},
},
NotFound: {
screen: NotFoundScreen,
linking: {
path: '*',
},
},
},
});
Result Navigation State

通过此配置,路径 /users/42 将解析为以下状态对象:

¥With this configuration, the path /users/42 will resolve to the following state object:

const state = {
routes: [
{
name: 'Home',
state: {
index: 1,
routes: [
{ name: 'Feed' },
{
name: 'Profile',
params: { id: '42' },
},
],
},
},
],
};
警告

initialRouteName 只会将屏幕添加到 React Navigation 的状态。如果你的应用在网络上运行,则浏览器的历史记录将不包含此屏幕,因为用户从未访问过它。因此,如果用户按下浏览器的后退按钮,它不会返回到此屏幕。

¥The initialRouteName will add the screen to React Navigation's state only. If your app is running on the Web, the browser's history will not contain this screen as the user has never visited it. So, if the user presses the browser's back button, it'll not go back to this screen.

另一件需要记住的事情是,不可能通过 URL 将参数传递到初始屏幕。因此,请确保你的初始路由不需要任何参数或在屏幕配置中指定 initialParams 来传递所需的参数。

¥Another thing to keep in mind is that it's not possible to pass params to the initial screen through the URL. So make sure that your initial route doesn't need any params or specify initialParams in the screen configuration to pass the required params.

在这种情况下,URL 中的任何参数仅传递到与路径模式 users/:id 匹配的 Profile 屏幕,而 Feed 屏幕不接收任何参数。如果你想在 Feed 屏幕中具有相同的参数,你可以指定 自定义 getStateFromPath 函数 并复制这些参数。

¥In this case, any params in the URL are only passed to the Profile screen which matches the path pattern users/:id, and the Feed screen doesn't receive any params. If you want to have the same params in the Feed screen, you can specify a custom getStateFromPath function and copy those params.

同样,如果你想从子屏幕访问父屏幕的参数,你可以使用 React 上下文 来公开它们。

¥Similarly, if you want to access params of a parent screen from a child screen, you can use React Context to expose them.

匹配精确路径

¥Matching exact paths

默认情况下,为每个屏幕定义的路径将与相对于其父屏幕路径的 URL 进行匹配。考虑以下配置:

¥By default, paths defined for each screen are matched against the URL relative to their parent screen's path. Consider the following config:

const ProfileTabs = createBottomTabNavigator({
screens: {
Profile: {
screen: HomeScreen,
linking: {
path: 'users/:id',
},
},
},
});

const RootStack = createStackNavigator({
screens: {
Home: {
screen: ProfileTabs,
linking: {
path: 'feed',
},
},
},
});

在这里,你为 Home 屏幕以及子 Profile 屏幕定义了 path 属性。配置文件屏幕指定路径 users/:id,但由于它嵌套在具有路径 feed 的屏幕内,因此它将尝试匹配模式 feed/users/:id

¥Here, you have a path property defined for the Home screen, as well as the child Profile screen. The profile screen specifies the path users/:id, but since it's nested inside a screen with the path feed, it'll try to match the pattern feed/users/:id.

这将导致 URL /feed 导航到 Home 屏幕,/feed/users/cal 导航到 Profile 屏幕。

¥This will result in the URL /feed navigating to Home screen, and /feed/users/cal navigating to the Profile screen.

在这种情况下,使用 /users/cal 这样的 URL 导航到 Profile 屏幕比使用 /feed/users/cal 更有意义。为此,你可以将相对匹配行为覆盖为 exact 匹配:

¥In this case, it makes more sense to navigate to the Profile screen using a URL like /users/cal, rather than /feed/users/cal. To achieve this, you can override the relative matching behavior to exact matching:

const ProfileTabs = createBottomTabNavigator({
screens: {
Profile: {
screen: HomeScreen,
linking: {
path: 'users/:id',
exact: true,
},
},
},
});

const RootStack = createStackNavigator({
screens: {
Home: {
screen: ProfileTabs,
linking: {
path: 'feed',
},
},
},
});

exact 属性设置为 true 时,Profile 将忽略父屏幕的 path 配置,你将能够使用 users/cal 等 URL 导航到 Profile

¥With exact property set to true, Profile will ignore the parent screen's path config and you'll be able to navigate to Profile using a URL like users/cal.

从路径中省略屏幕

¥Omitting a screen from path

有时,你可能不希望路径中包含屏幕的路由名称。例如,假设你有一个 Home 屏幕和以下配置。在浏览器中打开页面时,你将获得 /home 作为 URL:

¥Sometimes, you may not want to have the route name of a screen in the path. For example, let's say you have a Home screen and the following config. When the page is opened in the browser you'll get /home as the URL:

const RootStack = createStackNavigator({
screens: {
Home: {
screen: ProfileScreen,
linking: {
path: 'home',
},
},
Profile: {
screen: HomeScreen,
linking: {
path: 'users/:id',
},
},
},
});

但如果访问主屏幕时 URL 是 / 就更好了。

¥But it'll be nicer if the URL was just / when visiting the home screen.

你可以指定一个空字符串作为路径,或者根本不指定路径,React Navigation 不会将屏幕添加到路径中(就像将空字符串添加到路径中一样,这不会改变任何内容):

¥You can specify an empty string as path or not specify a path at all, and React Navigation won't add the screen to the path (think of it like adding empty string to the path, which doesn't change anything):

const RootStack = createStackNavigator({
screens: {
Home: {
screen: ProfileScreen,
linking: {
path: '',
},
},
Profile: {
screen: HomeScreen,
linking: {
path: 'users/:id',
},
},
},
});

序列化和解析参数

¥Serializing and parsing params

由于 URL 是字符串,因此在构造路径时,路由的任何参数也会转换为字符串。

¥Since URLs are strings, any params you have for routes are also converted to strings when constructing the path.

例如,假设你有一个带有以下配置的 URL /chat/1589842744264

¥For example, say you have the URL /chat/1589842744264 with the following config:

const RootStack = createStackNavigator({
screens: {
Chat: {
screen: ChatScreen,
linking: {
path: 'chat/:date',
},
},
},
});

处理 URL 时,你的参数将如下所示:

¥When handling the URL, your params will look like this:

{ date: '1589842744264' }

在这里,date 参数被解析为字符串,因为 React Navigation 不知道它应该是时间戳,因此也不知道数字。你可以通过提供用于解析的自定义函数来自定义它:

¥Here, the date param was parsed as a string because React Navigation doesn't know that it's supposed to be a timestamp, and hence number. You can customize it by providing a custom function to use for parsing:

const RootStack = createStackNavigator({
screens: {
Chat: {
screen: ChatScreen,
linking: {
path: 'chat/:date',
parse: {
date: Number,
},
},
},
},
});

你还可以提供自己的函数来序列化参数。例如,假设你想在路径中使用 DD-MM-YYYY 格式而不是时间戳:

¥You can also provide a your own function to serialize the params. For example, let's say that you want to use a DD-MM-YYYY format in the path instead of a timestamp:

const RootStack = createStackNavigator({
screens: {
Chat: {
screen: ChatScreen,
linking: {
path: 'chat/:date',
parse: {
date: (date) => new Date(date).getTime(),
},
stringify: {
date: (date) => {
const d = new Date(date);

return d.getFullYear() + '-' + d.getMonth() + '-' + d.getDate();
},
},
},
},
},
});

根据你的要求,你可以使用此功能来解析和字符串化更复杂的数据。

¥Depending on your requirements, you can use this functionality to parse and stringify more complex data.

高级案例

¥Advanced cases

对于某些高级情况,指定映射可能还不够。为了处理这种情况,你可以指定一个自定义函数将 URL 解析为状态对象 (getStateFromPath),并指定一个自定义函数将状态对象序列化为 URL (getPathFromState)。

¥For some advanced cases, specifying the mapping may not be sufficient. To handle such cases, you can specify a custom function to parse the URL into a state object (getStateFromPath), and a custom function to serialize the state object into an URL (getPathFromState).

示例:

¥Example:

const linking = {
prefixes: ['https://mychat.com', 'mychat://'],
getStateFromPath: (path, options) => {
// Return a state object here
// You can also reuse the default logic by importing `getStateFromPath` from `@react-navigation/native`
},
getPathFromState(state, config) {
// Return a path string here
// You can also reuse the default logic by importing `getPathFromState` from `@react-navigation/native`
},

// ...
};

在线运行

¥Playground

Playground 不适用于静态配置。

¥Playground is not available for static config.