在页面之间导航
了解如何创建链接以在页面之间移动。
Expo Router 使用 "links" 在应用的页面之间移动。这在概念上类似于网络如何使用 <a>
标签和 href
属性。
¥Expo Router uses "links" to move between pages in the app. This is conceptually similar to how the web works with <a>
tags and the href
attribute.
app
index.tsx
about.tsx
user
[id].tsx
在以下示例中,有两个导航到不同路由的 Link
组件。
¥In the following example, there are two Link
components which navigate to different routes.
import { View } from 'react-native';
import { Link } from 'expo-router';
export default function Page() {
return (
<View>
<Link href="/about">About</Link>
{/* ...other links */}
<Link href="/user/bacon">View user</Link>
</View>
);
}
按钮
¥Buttons
默认情况下,Link 组件将子组件封装在 <Text>
组件中,这对于可访问性很有用,但并不总是需要的。你可以通过传递 asChild
属性 来自定义组件,这会将所有 props 转发到 Link
组件的第一个子组件。子组件必须支持 onPress
和 onClick
属性,href
和 role
也会被传递下去。
¥The Link component wraps the children in a <Text>
component by default, this is useful for accessibility but not always desired. You can customize the component by passing the asChild
prop, which will forward all props to the first child of the Link
component. The child component must support the onPress
and onClick
props, href
and role
will also be passed down.
import { Pressable, Text } from 'react-native';
import { Link } from 'expo-router';
export default function Page() {
return (
<Link href="/other" asChild>
<Pressable>
<Text>Home</Text>
</Pressable>
</Link>
);
}
了解原生导航
¥Understanding native navigation
Expo Router 使用基于堆栈的导航模型,其中你导航到的每条新路由都会添加到堆栈中。
¥Expo Router uses a stack-based navigation model, where each new route you navigate to is added to a stack.
app
_layout.tsx
<Stack />
index.tsx
feed
_layout.tsx
<Stack />
index.tsx
profile
_layout.tsx
<Stack />
index.tsx
settings
_layout.tsx
<Stack />
index.tsx
在上面的示例中,app/_layout.tsx 使用了一个 <Stack />
导航器。从 /feed
路由导航到 /profile
路由会导致堆栈为 ['/feed', '/profile']
。如果你随后导航到 /settings
,堆栈将变为 ['/feed', '/profile', '/settings']
。虽然这可能类似于传统的 Web 导航,但一个关键区别是屏幕可以有多个子堆栈,每个子堆栈都独立控制。这称为并行路由。
¥In the above example, the app/_layout.tsx uses a <Stack />
navigator. Navigating from the /feed
route to the /profile
route results in the stack being ['/feed', '/profile']
. If you then navigate to /settings
, the stack becomes ['/feed', '/profile', '/settings']
. While this may resemble traditional web navigation, a key distinction is that screens can have multiple child stacks, each independently controlled. This is known as parallel routing.
app
_layout.tsx
<Tabs />
(fruit)
_layout.tsx
<Stack />
apple.tsx
orange.tsx
(vegetable)
_layout.tsx
<Stack />
carrot.tsx
potato.tsx
在上面的示例中,app/_layout 引入了一个 <Tabs />
导航器,而其他两个布局文件渲染了一个 <Stack />
。浏览每个页面都会产生类似 [['/apple', '/orange'], ['/carrot', '/potato']]
的历史记录。请注意,不是单个堆栈,而是包含两个子堆栈的父堆栈。
¥In the above example, app/_layout introduces a <Tabs />
navigator, while the other two layout files render a <Stack />
. Navigating through each page would result in a history like [['/apple', '/orange'], ['/carrot', '/potato']]
. Notice that instead of a single stack, there's a parent stack containing two child stacks.
虽然在堆栈中前进很简单,但由于非线性历史记录,向后移动可能更复杂。
¥While advancing in a stack is straightforward, moving backward can be more complex due to the non-linear history.
考虑常见的移动体验:当你从链接打开应用并按返回时,你可能会在退出应用之前看到不熟悉的屏幕。这演示了堆栈如何使用锚点路由(也称为初始路由)维护自己的历史记录。这就是为什么 back()
有时被称为 "pop"("push" 的反面)或 "展开堆栈"。
¥Consider a common mobile experience: when you open an app from a link and press back, you might see unfamiliar screens before exiting the app. This demonstrates how stacks maintain their own history using anchor routes (also called initial routes). This is why back()
is sometimes called a "pop" (the reverse of "push") or "unwinding the stack".
为了处理向后导航,Expo Router 提供了多种功能:back
会将你从堆栈的历史记录中向后移动。同时,dismiss
仅在当前堆栈内返回。
¥To handle backwards navigation, Expo Router offers multiple functions: back
moves you backward in the stack's history. At the same time, dismiss
only goes back within the current stack.
dismissTo
函数是唯一的 - 它可以让你前进或后退。为之前访问过的路由调用 dismissTo
将关闭屏幕,直到到达该路由。如果该路由不在历史记录中,它将向前推进到该路由。
¥The dismissTo
function is unique—it can move you forward or backward. Calling dismissTo
for a previously visited route will dismiss screens until that route is reached. If the route isn't in the history, it will push forward to that route.
此外,replace
方法允许你用新路由替换堆栈中的当前路由,而无需添加到堆栈。
¥Additionally, the replace
method allows you to replace the current route in the stack with a new one, without adding to the stack.
要进行导航,你可以提供完整路径 (/profile/settings
)、相对路径 (../settings
) 或通过传递对象 ({ pathname: 'profile', params: { id: '123' } }
)。
¥To navigate, you can provide a full path (/profile/settings
), a relative path (../settings
), or by passing an object ({ pathname: 'profile', params: { id: '123' } }
).
相对导航
¥Relative navigation
相对 URL 是带有 ./
的 URL 前缀,例如 ./article
或 ./article/
。相对 URL 是相对于当前渲染的屏幕解析的。
¥A relative URL is a URL prefix with ./
, such as ./article
, or ./article/
. Relative URLs are resolved relative to the current rendered screen.
当前屏幕的 URL 是文档 URL(没有尾部斜杠的 URL),因此相对 URL 将相对于目录进行解析。当当前屏幕由 index
文件渲染时,这可能会造成混淆,因为相对 URL 是从 URL 的目录而不是文件系统解析的。通过使用 relativeToDirectory
选项,Expo Router 将把当前 URL 视为目录 URL。
¥The URL of the current screen is a document URL (a URL without a trailing slash), so relative URLs will be resolved relative to the directory. This can be confusing when the current screen is rendered by an index
file as the relative URL is resolved from the URL's directory, not the file system. By using the relativeToDirectory
option, Expo Router will instead treat the current URL as a directory URL.
Href | 当前 URL | relativeToDirectory | 结果 |
---|---|---|---|
./article | /route/v1 | /route/article | |
./article | /route/v1 | true | /route/v1/article |
../article | /route/v1 | /article | |
../article | /route/v1 | true | /route/article |
// Using `relativeToDirectory` with Link
<Link href="./article" relativeToDirectory>Go to article</Link>
// Using `relativeToDirectory` with the imperative API
router.push("./article", { relativeToDirectory: true })
router.navigate("./article", { relativeToDirectory: true })
router.replace("./article", { relativeToDirectory: true })
不支持不带./
前缀的相对 URL,例如article
。
链接到动态路由
¥Linking to dynamic routes
动态路由和查询参数可以静态提供,也可以使用方便的 Href 对象提供。
¥Dynamic routes and query parameters can be provided statically or with the convenience Href object.
import { Link } from 'expo-router';
import { View } from 'react-native';
export default function Page() {
return (
<View>
<Link
href={{
pathname: '/user/[id]',
params: { id: 'bacon' }
}}>
View user
</Link>
</View>
);
}
推屏
¥Pushing screens
默认情况下,通过推送新路由或展开到现有路由,将 navigate
链接到导航堆栈中最近的路由。你可以使用 push
属性始终将路由推入堆栈。
¥By default, links navigate
to the nearest route in the navigation stack, either by pushing a new route or unwinding to an existing route. You can use the push
prop to always push the route onto the stack.
import { Link } from 'expo-router';
export default function Page() {
return (
<View>
<Link push href="/feed">Login</Link>
</View>
);
}
更换屏幕
¥Replacing screens
默认情况下,将 "push" 路由链接到导航堆栈。它遵循与 navigation.navigate()
相同的规则。这意味着当用户返回时,上一个屏幕将可用。你可以使用 replace
属性替换当前屏幕,而不是推送新屏幕。
¥By default, links "push" routes onto the navigation stack. It follows the same rules as navigation.navigate()
. This means that the previous screen will be available when the user navigates back. You can use the replace
prop to replace the current screen instead of pushing a new one.
import { Link } from 'expo-router';
export default function Page() {
return (
<View>
<Link replace href="/feed">Login</Link>
</View>
);
}
使用 router.replace()
强制替换当前屏幕。
¥Use router.replace()
to replace the current screen imperatively.
原生导航并不总是支持 replace
。例如在 X 上,你无法直接从配置文件 "replace" 到推文,这是因为 UI 需要一个后退按钮才能返回到提要或其他顶层选项卡屏幕。在这种情况下,替换将切换到提要选项卡,并将推文路由推到其顶部,或者如果你在提要选项卡内的其他推文上,它将用新推文替换当前推文。通过使用 unstable_settings
,可以在 Expo Router 中获得这种确切的行为。
¥Native navigation does not always support replace
. For example on X, you wouldn't be able to "replace" directly from a profile to a tweet, this is because the UI requires a back button to return to the feed or other top-level tab screen. In this case, replace would switch to the feed tab, and push the tweet route on top of it, or if you were on a different tweet inside the feed tab, it would replace the current tweet with the new tweet. This exact behavior can be obtained in Expo Router by using unstable_settings
.
命令式导航
¥Imperative navigation
你还可以使用 router
对象进行命令式导航。当你需要在 React 组件之外执行导航操作时(例如在事件处理程序或实用程序函数中),这很有用。
¥You can also navigate imperatively using the router
object. This is useful when you need to perform a navigation action outside a React component, such as in an event handler or a utility function.
import { router } from 'expo-router';
export function logout() {
router.replace('/login');
}
router
对象是不可变的,包含以下功能:
¥The router
object is immutable and contains the following functions:
-
导航:
(href: Href, options: LinkToOptions) => void
。执行navigate
操作。¥navigate:
(href: Href, options: LinkToOptions) => void
. Perform anavigate
action. -
推送:
(href: Href, options: LinkToOptions) => void
。执行push
操作。¥push:
(href: Href, options: LinkToOptions) => void
. Perform apush
action. -
替换:
(href: Href, options: LinkToOptions) => void
。执行replace
操作。¥replace:
(href: Href, options: LinkToOptions) => void
. Perform areplace
action. -
返回:
() => void
。导航回上一条路由。¥back:
() => void
. Navigate back to previous route. -
canGoBack:
() => boolean
如果存在有效的历史堆栈并且back()
函数可以弹回,则返回true
。¥canGoBack:
() => boolean
Returnstrue
if a valid history stack exists and theback()
function can pop back. -
setParams:
(params: Record<string, string>) => void
更新当前选定路由的查询参数。¥setParams:
(params: Record<string, string>) => void
Update the query params for the currently selected route.
自动补齐
¥Autocomplete
Expo Router 可以自动为应用中的所有路由生成静态 TypeScript 类型。这允许你对 href
使用自动补齐功能,并在使用无效链接时收到警告。请参阅 静态类型路由 了解更多信息。
¥Expo Router can automatically generate static TypeScript types for all routes in your app. This allows you to use autocomplete for href
s and get warnings when invalid links are used. See Statically Typed Routes for more information.
Web 行为
¥Web behavior
Expo Router 在网络上运行时支持标准 <a>
元素,但这将执行全页服务器导航。这比较慢并且没有充分利用 React。相反,Expo Router Link
组件将执行客户端导航,这将保留网站的状态并更快地导航。
¥Expo Router supports the standard <a>
element when running on web, however this will perform a full-page server-navigation. This is slower and doesn't take full advantage of React. Instead, the Expo Router Link
component will perform client-side navigation, which will preserve the state of the website and navigate faster.
还支持仅 Web 属性 target
、rel
和 download
。当在网络上运行时,这些将被传递到 <a>
元素。
¥The web-only attributes target
, rel
, and download
are also supported. These will be passed to the <a>
element when running on web.
客户端导航适用于单页应用和 静态渲染。
¥Client-side navigation works with both single-page apps, and static rendering.
在模拟器中的使用
¥Usage in simulators
有关如何在 Android 模拟器和 iOS 模拟器中模拟深层链接,请参阅 测试更新。
¥See Test the deep link to learn how to emulate deep links in Android Emulators and iOS Simulators.