This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
了解如何使屏幕无法通过客户端导航访问。
观看:使用受保护路由在 Expo Router 中使用受保护路由,根据身份验证状态限制屏幕访问。
概览
受保护屏幕允许你通过客户端导航防止用户访问某些路由。如果用户尝试导航到受保护屏幕,或者某个屏幕在处于活动状态时变为受保护状态,他们将被重定向到锚点路由(通常是 index 屏幕)或堆栈中的第一个可用屏幕。
import { Stack } from 'expo-router';
const isLoggedIn = false;
export function AppLayout() {
return (
<Stack>
<Stack.Protected guard={!isLoggedIn}>
<Stack.Screen name="login" />
</Stack.Protected>
<Stack.Protected guard={isLoggedIn}>
<Stack.Screen name="private" />
</Stack.Protected>
{}
</Stack>
);
}
在这个示例中,/private 路由无法访问,因为 guard 为 false。当用户尝试访问 /private 时,他们会被重定向到锚点路由,也就是 index 屏幕。
此外,如果用户当前位于 /private/page,并且 guard 条件变为 false,他们也会自动被重定向。
当某个屏幕的 guard 从 true 改为 false 时,它的所有历史记录条目都会从导航历史中移除。
多个受保护屏幕
在 Expo Router 中,一个屏幕在同一时间只能存在于一个活动路由组中。
你应该只在最合适的组或堆栈中声明一次屏幕。如果某个屏幕的可用性取决于逻辑,请将其包裹在条件组中,而不是重复声明该屏幕。
import { Stack } from 'expo-router';
const isLoggedIn = true;
const isAdmin = true;
export function AppLayout() {
return (
<Stack>
<Stack.Protected guard={true}>
<Stack.Screen name="profile" />
</Stack.Protected>
<Stack.Screen name="profile" /> // ❌ 不允许:重复的屏幕
</Stack>
);
}
嵌套受保护屏幕
受保护屏幕可以嵌套,以定义分层访问控制逻辑。
import { Stack } from 'expo-router';
const isLoggedIn = true;
const isAdmin = true;
export function AppLayout() {
return (
<Stack>
<Stack.Protected guard={isLoggedIn}>
<Stack.Protected guard={isAdmin}>
<Stack.Screen name="private" />
</Stack.Protected>
<Stack.Screen name="about" />
</Stack.Protected>
</Stack>
);
}
在这种情况下:
- 仅当用户已登录且是管理员时,
/private 才受保护。
/about 对任何已登录用户受保护。
使用默认重定向
如果访问被拒绝,导航器会将用户重定向到其锚点路由或第一个可用屏幕。
import { Stack } from 'expo-router';
const isLoggedIn = false;
export function AppLayout() {
return (
<Stack>
<Stack.Protected guard={isLoggedIn}>
<Stack.Screen name="index" />
<Stack.Screen name="private" />
</Stack.Protected>
<Stack.Screen name="login" />
</Stack>
);
}
在这个示例中,index 屏幕受到保护,且 guard 为 false,因此路由器会将用户重定向到第一个可用屏幕:login。
重定向到指定路由
当受保护路由需要重定向到指定路由时,使用 redirectTo 属性。它接受与 Link 相同的字符串或对象 href。
import { Stack } from 'expo-router';
const isLoggedIn = false;
export function AppLayout() {
return (
<Stack>
<Stack.Protected guard={isLoggedIn} redirectTo="/login">
<Stack.Screen name="private" />
</Stack.Protected>
<Stack.Screen name="login" />
</Stack>
);
}
Tabs 和 Drawer
受保护路由也适用于 Tabs 和 Drawer 导航器。
import { Tabs } from 'expo-router/js-tabs';
const isLoggedIn = false;
export default function TabLayout() {
return (
<Tabs>
<Tabs.Screen name="index" options={{ tabBarLabel: 'Home' }} />
<Tabs.Protected guard={isLoggedIn}>
<Tabs.Screen name="private" options={{ tabBarLabel: 'Private' }} />
<Tabs.Screen name="profile" options={{ tabBarLabel: 'Profile' }} />
</Tabs.Protected>
<Tabs.Protected guard={!isLoggedIn}>
<Tabs.Screen name="login" options={{ tabBarLabel: 'Login' }} />
</Tabs.Protected>
</Tabs>
);
}
自定义导航器
稳定版自定义导航器 API 适用于 SDK 58 及更高版本。
通过 createStandardRouterNavigator 或 integrateWithRouter 创建的导航器包含一个 .Protected 子项。请参阅自定义导航器以创建或集成一个导航器。
静态渲染注意事项
受保护屏幕仅在客户端进行评估。在静态站点生成期间,不会为受保护路由创建任何 HTML 文件。不过,如果用户知道这些路由的 URL,他们仍然可以直接请求对应的 HTML 或 JavaScript 文件。受保护屏幕不能替代服务器端身份验证或访问控制。