自定义链接
编辑页面
了解在使用 Expo Router 时如何通过 +native-intent 进行链接重定向并使用第三方深度链接。
For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.
Expo Router 使用一种扩展版的 Web 标准来在应用内进行导航。然而,原生应用并不总是符合基于服务器的路由。这在集成任何第三方服务时都可能导致不一致。例如,应用可以通过任意字符串或 intent 对象启动,而不是 URL。你可能需要自定义链接的常见场景有两种:
-
应用已关闭:当应用未打开时,传入的深度链接 URL 可能需要重写,以确保无缝导航。
-
应用已打开:当应用已经打开时,可能需要根据特定业务逻辑或用户交互来自定义 URL。这种逻辑可以是整个应用范围的全局逻辑,也可以局限于一组路由。
设置链接
有关如何在应用中设置和测试链接的说明,请参阅将链接引入你的应用指南。
重写传入的原生深度链接
Expo Router 始终会在“该 URL 指向应用内某个特定页面”的假设下解析 URL。然而,在实践中,这些 URL 的性质可能各不相同:
- 来自第三方提供商的唯一/推荐 URL:这类 URL 通常遵循特定的 schema,例如
<my-scheme>://<provider-hostname>/<uuid>,由外部来源生成,用于将用户导航到应用内指定内容。 - 来自旧版本的过期 URL:应用用户可能会遇到来自旧版本应用的 URL,这些 URL 可能指向过时或不存在的内容。妥善处理此类情况对于确保顺畅的用户体验至关重要。
在这类场景中,需要对 URL 进行重写,以便正确地指向某个路由。
为此,请在项目的 src/app 目录顶层创建一个名为 +native-intent.tsx 的特殊文件。此文件导出一个特殊的 redirectSystemPath 方法,用于处理 URL/path。调用时,它会接收一个包含两个属性的 options 对象:path 和 initial。
srcapp+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'; } }
重写传入的 Web 深度链接
在 Web 上处理深度链接与原生平台不同,因为初始路由流程的执行方式不同。Expo Router 无法为 Web 提供与 +native-intent 直接对应的方案,因为 Web 路由是在网站的 JavaScript 执行之前解析的,并且会因部署产物和你选择的提供商而有所不同。
因此,你应该根据自身需求实现以下模式之一:
- 服务器重定向:由于所有网站(包括静态页面)都托管在服务器上,因此可以考虑利用部署提供商提供的服务端重定向或中间件选项。这种方式非常适合面向 server 或 static 输出的部署。
- 客户端重定向:或者,你也可以在应用根目录的
_layout中管理 URL 重定向。这种方式非常适合目标为客户端渲染、且只有单一输出格式的项目。
请选择与你的部署策略和技术需求相匹配的模式,以确保在 Web 平台上无缝处理传入的深度链接。
重写 URL
当你的应用处于打开状态时,你可以在 _layout 文件中使用 usePathname() hook 来响应 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 方法中处理它。对于某些用例,这种方式可能更简单,但也有一些缺点:
- 仅适用于原生:此方法无法在 Web 上使用,因为
+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]); // 将 pathname 变化发送给第三方 useEffect(() => { thirdParty.sendEvent({ pathname }); }, [pathname]); return <Slot />; }
Universal Links 和多个域名
Expo Router 不需要为 Universal Links 和多个域名进行额外配置。传递给你的 App 的所有 URL 都会被解析。若要自定义应用的 URL scheme,请在应用配置中自定义 scheme 值。
强制使用 Web 链接
如果你希望 URL 首先由用户的浏览器进行解析,请将地址写为带有 http/https scheme 的完全限定 URL(FQDN)。使用完整 URL 可确保该链接被解释为 Web URL,并默认在用户的浏览器中打开。
这种方式适用于将用户引导到外部网站,或为其他应用提供 Universal Links。
<Link href="https://my-website.com/router/introduction" />
legacy_subscribe
重要
legacy_subscribe处于alpha 阶段,并在 SDK 52 中可用。
如果你正在使用一个不支持 Expo Router、但支持通过 Linking.subscribe 函数为现有项目提供 React Navigation 的第三方提供商,那么你可以使用 legacy_subscribe 作为替代 API。
不建议在新项目或集成中使用此 API。它与服务器端路由和静态渲染不兼容,并且在离线或低网络连接环境下会较难管理。