自定义链接
编辑
学习如何在使用 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 对象,包含两个属性:path 和 initial。
app+native-intent.tsx以下是一个应用实践的示例,说明如何在 +native-intent.tsx 文件中使用 redirectSystemPath。通过遵循此示例,您可以确保应用的 URL 处理功能的稳定性和可靠性,并降低意外错误和崩溃的风险。
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 执行之前被解析,并且会根据部署输出和您选择的提供商而变化。
因此,您应实现以下模式之一,以最适合您的要求:
- 服务器重定向:由于所有网站,包括静态页面,都托管在服务器上,请考虑利用您部署提供商提供的服务器端重定向或中间件选项。这种方法非常适合针对 server 或 static 输出的部署。
- 客户端重定向:或者,您可以在应用根
_layout中管理 URL 重定向。这种方法适合处理单一输出格式目标为客户端渲染的项目。
选择与您的部署策略和技术要求相符的模式,以确保无缝处理网页平台上的传入深度链接。
重写 URLs
当您的应用打开时,您可以使用 usePathname() 钩子在 _layout 文件中响应 URL 更改。_layout 的位置决定了订阅的范围。
- 全局:将逻辑添加到根
_layout文件 - 局部:向现有目录添加
_layout文件(或创建一个新的 组目录)
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在应用的上下文之外处理。这意味着您无法访问其他逻辑,例如用户身份验证状态或当前路由的状态。
向第三方服务发送导航事件
以下是如何向外部服务(例如分析或日志服务)发送导航事件的基本示例。请咨询您的提供商以获取具体说明。
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。它的用法与服务器端路由和 静态渲染 不兼容,并且在离线或网络连接不良的环境中难以管理。