自定义链接

编辑

学习如何在使用 Expo Router 时执行链接重定向并利用第三方深度链接与 +native-intent。


Expo Router 使用扩展版的网络标准在应用程序中导航。然而,原生应用并不总是符合基于服务器的路由。这可能导致在集成任何第三方服务时出现不匹配。例如,应用可以使用任意字符串或意图对象启动,而不是 URL。在以下两种常见场景中,您可能需要自定义链接:

  • 应用关闭:当应用未打开时,传入的深度链接 URL 可能需要重写以确保无缝导航。

  • 应用打开:当应用已打开时,可能需要根据特定的业务逻辑或用户交互进行 URL 自定义。此逻辑可以是全局适用于整个应用,或者局部适用于一组路由。

设置链接

请参阅 将链接引入您的应用 指南,了解如何在您的应用中设置和测试链接。

重写传入的原生深度链接

Expo Router 将始终假设 URL 目标是应用中的特定页面。然而,实际上,这些 URL 的性质可以有所不同:

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

在这样的场景中,需要重写 URL 以正确目标路由。

为此,请在项目的 app 目录的顶层创建一个名为 +native-intent.tsx 的特殊文件。此文件导出一个特殊的 redirectSystemPath 方法,旨在处理 URL/路径处理。当调用时,它接收一个 options 对象,包含两个属性:pathinitial

app
+native-intent.tsx

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

app/+native-intent.tsx
import ThirdPartyService from 'third-party-sdk'; export function redirectSystemPath({ path, initial }) { try { if (initial) { // 虽然参数被称为 `path`,但不能保证这是一个路径或有效的 URL const url = new URL(path, 'myapp://app.home'); // 第三方 URL 的检测将根据提供商的不同而变化 if (url.hostname === '<third-party-provider-hostname>') { return ThirdPartyService.processReferringUrl(url).catch(() => { // 发生了错误 return '/unexpected-error'; }); } return path; } return path; } catch { // 在此函数内不要崩溃!相反,您应该将用户重定向 // 到一个自定义路由以处理意外错误,让他们可以报告事件 return '/unexpected-error'; } }

重写传入的网页深度链接

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

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

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

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

重写 URLs

当您的应用打开时,您可以使用 usePathname() 钩子在 _layout 文件中响应 URL 更改。_layout 的位置决定了订阅的范围。

  • 全局:将逻辑添加到根 _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

在原生应用中,重写 URL 的另一种方法是在 redirectSystemPath 方法中处理它。这种方法对于某些用例可能更简单,但也有一些缺点:

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

向第三方服务发送导航事件

以下是如何向外部服务(例如分析或日志服务)发送导航事件的基本示例。请咨询您的提供商以获取具体说明。

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(); // 执行服务初始化逻辑 useEffect(() => { thirdParty.register(); return () => { thirdParty.deregister(); }; }, [thirdParty]); // 将路径名称更改发送给第三方 useEffect(() => { thirdParty.sendEvent({ pathname }); }, [pathname]); return <Slot />; }

Universal Links 和多个域名

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

强制网页链接

如果您希望 URL 被用户的浏览器初步评估,请将地址写为具有 http/https 方案的完全合格 URL (FQDN)。使用完整 URL 可确保链接被解释为网页 URL,默认在用户的浏览器中打开。

这种方法对于将用户引导至外部网站或其他应用的 Universal Links 非常有效。

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

legacy_subscribe

legacy_subscribe 在 SDK 52 中实验性可用。

如果您使用的第三方提供商不支持 Expo Router,但通过 Linking.subscribe 函数支持 React Navigation(针对现有项目),您可以将 legacy_subscribe 用作替代 API。

不建议在新项目或集成中使用此 API。它的用法与服务器端路由和 静态渲染 不兼容,并且在离线或网络连接不良的环境中难以管理。