自定义链接

了解如何在使用 Expo Router 时执行链接重定向并使用 +native-intent 利用第三方深层链接。


Expo Router 使用扩展版本的网络标准来在应用中进行导航。然而,原生应用并不总是遵循基于服务器的路由。这可能在集成任何第三方服务时导致不一致。例如,应用可以通过任意字符串或意图对象而不是 URL 启动。有两种常见情况可能需要自定义链接:

🌐 Expo Router uses an extended version of web standards to navigate through an app. However, native apps do not always conform to server-based routing. This can lead to misalignment when integrating any third-party service. For example, apps can be launched with arbitrary strings or intent objects instead of URLs. There are two common scenarios where you may need to customize a link:

  • 应用已关闭:当应用未打开时,传入的深度链接 URL 可能需要重写,以确保顺畅导航。
  • 应用已打开:当应用已经打开时,可能需要根据特定的业务逻辑或用户交互进行 URL 定制。这一逻辑可以针对整个应用全局设置,或仅针对某些路由本地化设置。

设置链接

🌐 Setup linking

请参阅 将链接集成到你的应用 指南,了解如何在应用中设置和测试链接。

🌐 See the Linking into your app guide for instructions on how to set up and test linking in your app.

重写传入的原生深层链接

🌐 Rewrite incoming native deep links

Expo Router 总是假设 URL 指向应用中的特定页面来进行评估。然而实际上,这些 URL 的性质可能各不相同:

🌐 Expo Router will always evaluate a URL with the assumption that the URL targets a specific page within the app. However, in practice, these URLs can vary in nature:

  • 来自第三方提供商的唯一/引用 URL:这些 URL 通常遵循特定的模式,例如 <my-scheme>://<provider-hostname>/<uuid>,由外部来源生成,用于将用户引导到应用内的指定内容。
  • 来自以前版本的过时 URL:应用用户可能会遇到来自旧版本应用的 URL,这可能导致访问过时或不存在的内容。妥善处理此类情况对于确保流畅的用户体验至关重要。

在这种情况下,需要重写 URL 以正确定位路由。

🌐 In such scenarios, the URL needs to be rewritten to correctly target a route.

为了方便实现这一点,在项目的 app 目录顶层创建一个名为 +native-intent.tsx 的特殊文件。该文件导出一个用于处理 URL/路径的特殊 redirectSystemPath 方法。调用该方法时,它会接收一个包含两个属性 pathinitialoptions 对象。

🌐 To facilitate this, create a special file called +native-intent.tsx at the top level of your project's app directory. This file exports a special redirectSystemPath method designed to handle URL/path processing. When invoked, it receives an options object with two attributes: path and initial.

app
+native-intent.tsx

下面是一个示例,展示了如何在 +native-intent.tsx 文件中使用 redirectSystemPath 的实践。参考此示例,你可以确保应用的 URL 处理功能的稳定性和可靠性,并降低意外错误和崩溃的风险。

🌐 Here's an example the applies practices on how redirectSystemPath is used inside +native-intent.tsx file. Following this example, you can ensure the stability and reliability of your app's URL processing functionality and mitigate the risk of unexpected errors and crashes.

app/+native-intent.tsx
import ThirdPartyService from 'third-party-sdk'; export function redirectSystemPath({ path, initial }) { try { if (initial) { // While the parameter is called `path` there is no guarantee that this is a path or a valid URL const url = new URL(path, 'myapp://app.home'); // Detection of third-party URLs will change based on the provider if (url.hostname === '<third-party-provider-hostname>') { return ThirdPartyService.processReferringUrl(url).catch(() => { // Something went wrong return '/unexpected-error'; }); } return path; } return path; } catch { // Do not crash inside this function! Instead you should redirect users // to a custom route to handle unexpected errors, where they are able to report the incident return '/unexpected-error'; } }

重写传入的 Web 深层链接

🌐 Rewrite incoming web deep links

在网页上处理深层链接与原生平台不同,因为初始路由过程有所不同。Expo Router 无法为网页提供与 +native-intent 对应的直接功能,因为网页路由在网站的 JavaScript 执行之前就已解析,并且会根据部署输出和你选择的供应商而有所不同。

🌐 Handling deep links on the web differs from native platforms, as the initial routing process occurs differently. Expo Router cannot provide a direct counterpart to +native-intent for web, as web routing is resolved before the website's JavaScript is executed and will differ based upon deployment output and your chosen provider.

因此,你应该实现最适合你要求的以下模式之一:

🌐 As a result, you should implement one of the following patterns that best suits your requirements:

  • 服务器重定向:由于所有网站,包括静态页面,都托管在服务器上,因此可以考虑利用部署提供商提供的服务器端重定向或中间件选项。这种方法非常适合面向服务器静态输出的部署。
  • 客户端重定向:或者,你可以在应用的根目录 _layout 中管理 URL 重定向。这种方法非常适合针对客户端渲染且只有单一输出格式的项目。

选择与你的部署策略和技术要求相符的模式,以确保在 Web 平台上无缝处理传入的深层链接。

🌐 Choose the pattern that aligns with your deployment strategy and technical requirements to ensure seamless handling of incoming deep links on the web platform.

重写 URL

🌐 Rewrite URLs

当你的应用打开时,你可以使用 usePathname() 钩子对 _layout 文件中的 URL 变化作出反应。_layout 的位置决定了订阅的范围。

🌐 While your app is open, you can react to URL changes within your _layout files using the usePathname() hook. The location of the _layout dictates the scope of the subscription.

  • 全局:将逻辑添加到你的根 _layout 文件中
  • 本地化:向现有目录添加 _layout 文件(或创建一个新的 组目录
app/_layout.tsx
import { Slot, Redirect } from 'expo-router'; export default function RootLayout() { const pathname = usePathname(); if (pathname && !isUserAllowed(pathname)) { return <Redirect href="/home" />; } return <Slot />; }

使用 redirectSystemPath

🌐 Using redirectSystemPath

在原生应用中,重写 URL 的另一种方法是通过 redirectSystemPath 方法来处理。对于某些使用场景,这种方法可能更简单,但也存在一些缺点:

🌐 In native apps, an alternative way to rewrite a URL is to handle it within the redirectSystemPath method. This approach can be simpler for some use cases but comes with certain drawbacks:

  • 仅限原生:此方法在网页上无法使用,因为 +native-intent 仅在原生应用中可用。
  • 缺乏上下文+native-intent 在应用的上下文之外处理。这意味着你无法访问额外的逻辑,例如用户身份验证状态或当前路由的状态。

将导航事件发送给第三方服务

🌐 Sending navigation events to third-party services

下面是一个如何向外部服务(例如分析或日志服务)发送导航事件的基本示例。有关具体说明,请咨询你的服务提供商。

🌐 Below is a basic example of how to send navigation events to an external service, such as an analytics or logging service. Consult with your provider for specific instructions.

app/_layout.tsx
import ThirdPartyService from 'third-party-sdk'; import { Slot, usePathname } from 'expo-router'; const thirdParty = new ThirdPartyService(); export default function RootLayout() { const pathname = usePathname(); // Perform the service initiation logic useEffect(() => { thirdParty.register(); return () => { thirdParty.deregister(); }; }, [thirdParty]); // Send pathname changes to the third party useEffect(() => { thirdParty.sendEvent({ pathname }); }, [pathname]); return <Slot />; }

通用链接和多个域

🌐 Universal Links and multiple domains

Expo Router 无需为通用链接和多个域名进行额外配置。提供给你应用的所有 URL 都将被评估。要自定义应用的 URL 方案,你应该在应用配置中自定义 scheme

🌐 Expo Router does not require additional configuration for Universal Links and multiple domains. All URLs provided to your App will be evaluated. To customize the URL scheme(s) for your app, your should customize the scheme value in your app config.

强制网络链接

🌐 Forcing web links

如果你希望 URL 最初由用户的浏览器进行评估,请将地址写成带有 http/https 方案的完全限定 URL(FQDN)。使用完整的 URL 可以确保链接被解释为网页 URL,并默认在用户的浏览器中打开。

🌐 If you want a URL to be initially evaluated by the user's browser, write the address as a Fully Qualified URL (FQDN) with an http/https scheme. Using a complete URL ensures that the link is interpreted as a web URL and opened in the user's browser by default.

这种方法可有效地将用户引导至外部网站或其他应用的通用链接。

🌐 This approach is effective for directing users to external websites or Universal Links for other apps.

<Link href="https://my-website.com/router/introduction" />

legacy_subscribe

重要 legacy_subscribe 目前处于 alpha 版本,并可在 SDK 52 中使用。

如果你正在使用不支持 Expo Router 的第三方提供商,但通过 Linking.subscribe 函数支持现有项目中的 React Navigation,你可以使用 legacy_subscribe 作为替代 API。

🌐 If you're using a third-party provider that doesn't support Expo Router but does support React Navigation via the Linking.subscribe function for existing projects, you can use legacy_subscribe as an alternative API.

不建议在新的项目或集成中使用此 API。它的使用与服务端路由和静态渲染不兼容,并且在离线或网络连接较差的环境中管理起来可能具有挑战性。

🌐 Using this API is not recommended for new projects or integrations. Its usage is incompatible with Server Side Routing and Static Rendering, and can be challenging to manage while offline or in a low network connectivity environment.