受保护的路由
了解如何使屏幕无法通过客户端导航访问。
受保护的路由在 SDK 53 及更高版本中可用。
受保护的屏幕允许你阻止用户使用客户端导航访问某些路由。如果用户尝试导航到受保护的屏幕,或者如果屏幕在活动状态下受到保护,他们将被重定向到锚点路由(通常是索引屏幕)或堆栈中第一个可用的屏幕。
¥Protected screens allow you to prevent users from accessing certain routes using client-side navigation. If a user tries to navigate to a protected screen, or if a screen becomes protected while it is active, they will be redirected to the anchor route (usually the index screen) or the first available screen in the stack.
app
_layout.tsx
index.tsx
about.tsx
login.tsx
Should only be available while not authenticated
private
_layout.tsx
Should only be available while authenticated
index.tsx
page.tsx
export { 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>
{/* Expo Router includes all routes by default. Adding Stack.Protected creates exceptions for these screens. */}
</Stack>
);
}
在此示例中,由于 guard
为 false,因此无法访问 /private
路由。当用户尝试访问 /private
时,他们会被重定向到锚点路由,即索引屏幕。
¥In this example, the /private
route is inaccessible because the guard
is false. When a user attempts to access /private
, they are redirected to the anchor route, which is the index screen.
此外,如果用户在 /private/page
上并且 guard
条件更改为 false,他们将被自动重定向。
¥Additionally, if the user is on /private/page
and the guard
condition changes to false, they will be redirected automatically.
当屏幕的保护状态从 true 更改为 false 时,其所有历史记录条目都将从导航历史记录中删除。
¥When a screen's guard is changed from true to false, all it's history entries will be removed from the navigation history.
多个受保护屏幕
¥Multiple protected screens
在 Expo Router 中,一个屏幕一次只能存在于一个活动路由组中。
¥In Expo Router, a screen can only exist in one active route group at a time.
你应该只在最合适的组或堆栈中声明一次屏幕。如果屏幕的可用性取决于逻辑,请将其封装在条件组中,而不是复制屏幕。
¥You should only declare a screen only once, in the most appropriate group or stack. If a screen's availability depends on logic, wrap it in a conditional group instead of duplicating the screen.
export { 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" /> // ❌ Not allowed: duplicate screen
</Stack>
);
}
嵌套受保护屏幕
¥Nesting protected screens
受保护的屏幕可以嵌套,以定义分层访问控制逻辑。
¥Protected screens can be nested to define hierarchical access control logic.
export { 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="protected" />
</Stack.Protected>
<Stack.Screen name="about" />
</Stack.Protected>
</Stack>
);
}
本例中:
¥In this case:
-
仅当用户登录且为管理员时,
/private
才受保护。¥
/private
is only protected if the user is logged in and is an admin. -
/about
对任何登录用户均受保护。¥
/about
is protected to any logged-in user.
回退到特定屏幕
¥Falling back to a specific screen
你可以将导航器配置为在访问被拒绝时回退到特定屏幕。
¥You can configure the navigator to fall back to a specific screen if access is denied.
app
_layout.tsx
index.tsx
about.tsx
login.tsx
private
_layout.tsx
index.tsx
page.tsx
export { 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>
);
}
此处,由于索引屏幕受保护且 protected 为 false,因此路由会重定向到第一个可用的屏幕 — 登录。
¥Here, because the index screen is protected and the protected is false, the router redirects to the first available screen — login.
静态渲染注意事项
¥Static rendering considerations
受保护的屏幕仅在客户端进行评估。在静态站点生成期间,不会为受保护的路由创建 HTML 文件。但是,如果用户知道这些路由的 URL,他们仍然可以直接请求相应的 HTML 或 JavaScript 文件。受保护的屏幕不能替代服务器端身份验证或访问控制。
¥Protected screens are evaluated on the client side only. During static site generation, no HTML files are created for protected routes. However, if users know the URLs of these routes, they can still request the corresponding HTML or JavaScript files directly. Protected screens are not a replacement for server-side authentication or access control.