了解如何在使用 Expo Router 时执行链接重定向并使用 +native-intent 利用第三方深层链接。
Expo Router 使用扩展版本的 Web 标准来浏览应用。但是,原生应用并不总是符合基于服务器的路由。这可能会导致集成任何第三方服务时出现错位。例如,可以使用任意字符串或意图对象而不是 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 可能需要重写以确保无缝导航。
¥App Closed: When the app is not open, incoming deep-link URLs may require rewriting to ensure seamless navigation.
应用已打开:当应用已经打开时,可能需要根据特定的业务逻辑或用户交互自定义 URL。此逻辑可以是整个应用的全局逻辑,也可以本地化为一组路由。
¥App Open: When the app is already open, URL customization may be necessary based on specific business logic or user interactions. This logic can be global for the entire app, or localized to a set of routes.
¥Setup linking
请参阅 链接 指南,了解如何在你的应用中设置和测试链接。
¥See the Linking guide for instructions on how to set up and test linking in your app.
¥Rewrite incoming native deep links
Expo Router 将始终评估 URL,并假设该 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>
),并由外部源生成,以将用户导航到应用内的指定内容。
¥Unique/Referred URLs from third-party providers: These URLs often follow a specific schema, such as <my-scheme>:://<provider-hostname>/<uuid>
, and are generated by external sources to navigate users to designated content within the app.
以前版本的过时 URL:应用用户可能会遇到来自旧版本应用的 URL,这可能会导致内容过时或不存在。妥善处理此类情况以确保流畅的用户体验至关重要。
¥Stale URLs from previous versions: App users might encounter URLs from older versions of the app, which could lead to outdated or non-existent content. It's crucial to handle such scenarios gracefully to ensure a smooth user experience.
在这种情况下,需要重写 URL 以正确定位路由。
¥In such scenarios, the URL needs to be rewritten to correctly target a route.
为了方便起见,请在项目的应用目录的顶层创建一个名为 +native-intent.tsx 的特殊文件。此文件导出一个独特的 redirectSystemPath
方法,旨在处理 URL/路径处理。
¥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 unique redirectSystemPath
method designed to handle URL/path processing.
app
+native-intent.tsx
redirectSystemPath()
redirectSystemPath
是一种用于处理原生应用中的 URL 的特殊方法。调用时,它会收到一个具有两个属性的 options
对象:
¥The redirectSystemPath
is a special method used to process URLs in native apps. When it is invoked, it receives an options
object with two attributes:
路径:表示正在处理的 URL 或路径。
¥path: Represents the URL or path undergoing processing.
初始:布尔标志,指示这是否是应用的初始 URL。
¥initial: A boolean flag indicating whether this is the app's initial URL.
此方法的返回值应为 string
或 Promise<string>
。请注意,在此方法中抛出错误可能会导致应用崩溃。强烈建议将代码封装在 try/catch
块中,并在适当的时候使用 .catch()
语句。
¥This method's return value should be either a string
or a Promise<string>
. Do note that throwing errors within this method may result in app crashes. It's highly recommended to wrap your code inside a try/catch
block and utilize .catch()
statements when appropriate.
通过遵循这些最佳实践,你可以确保应用的 URL 处理功能的稳定性和可靠性,并降低意外错误和崩溃的风险。
¥By following these best practices, you can ensure the stability and reliability of your app's URL processing functionality and mitigate the risk of unexpected errors and crashes.
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';
}
}
¥Rewrite incoming web deep-links
处理网络上的深层链接与原生平台不同,因为初始路由过程不同。Expo Router 无法为 Web 提供与 +native-intent
直接对应的功能,因为 Web 路由是在执行网站的 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:
服务器重定向:由于所有网站(包括静态页面)都托管在服务器上,请考虑利用部署提供商提供的服务器端重定向或中间件选项。这种方法非常适合针对服务器或静态输出的部署。
¥Server Redirect: Since all websites, including static pages, are hosted on a server, consider leveraging server-side redirection or middleware options provided by your deployment provider. This approach is well-suited for deployments targeting server or static outputs.
客户端重定向:或者,你可以在应用的根 _layout
中管理 URL 重定向。这种方法非常适合具有针对客户端渲染的单一输出格式的项目。
¥Client Redirect: Alternatively, you can manage URL redirects within your app's root _layout
. This approach is ideal for projects with a single output format targeting client-side rendering.
选择与你的部署策略和技术要求相符的模式,以确保在 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.
¥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
文件
¥global: Add the logic to your root _layout
file
本地化:将 _layout
文件添加到现有目录(或创建一个新的(组目录)[/router/layouts/#groups])
¥localized: Add a _layout
file to an existing directory (or create a new (group directory)[/router/layouts/#groups])
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:
仅限原生:此方法不适用于 Web,因为 +native-intent
仅适用于原生应用。
¥Native-only: This method will not work on the web, as +native-intent
is only available in native apps.
缺少上下文:+native-intent
在你的应用上下文之外进行处理。这意味着你将无法访问其他逻辑,例如用户身份验证状态或当前路由的状态。
¥Lacks context: +native-intent
is processed outside the context of your app. This means you won't have access to additional logic, such as user authentication status or the current route's state.
¥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.
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 可确保链接被解释为 Web 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" />