Маршрутизация
Разделите приложение на маршруты с общим макетом, ссылками с сочетаниями клавиш и историей.
В этой главе
- Файлы как маршруты
- Общий макет
- Возврат назад
- Динамические сегменты
App Router сопоставляет файлы в app/ с URL по соглашениям Next.js App Router. Адресная строка и история браузера синхронизированы, поэтому переходы назад, вперёд и прямые ссылки работают, пока интерфейс рендерится в консоли.
Файлы как маршруты
Перенесите список в отдельный маршрут и добавьте страницу настроек:
app/ layout.tsx page.tsx → /Добавлено: deployments/Добавлено: page.tsx → /deploymentsДобавлено: [id]/page.tsx → /deployments/dpl_8fK2Добавлено: settings/Добавлено: page.tsx → /settingsОбщий макет
layout.tsx оборачивает каждую страницу и сохраняет своё состояние при переходах. Разместите в нём верхнюю панель и навигацию.
Добавлено: import type { ReactNode } from "react";Добавлено: import { Box, Spacer, Text } from "@textjs/app";Добавлено: import Link from "@textjs/app/link";Добавлено: import { usePathname } from "@textjs/app/navigation";Добавлено: Добавлено: export const metadata = { title: { default: "Acme Deploys", template: "%s · Acme" } };Добавлено: Добавлено: export default function RootLayout({ children }: { children?: ReactNode }) {Добавлено: const pathname = usePathname();Добавлено: return (Добавлено: <Box className="flex-col grow">Добавлено: <Box className="flex-row h-1 px-1 gap-2">Добавлено: <Text bold>▼ Acme</Text>Добавлено: <Text color="subtle">{`acme.local${pathname === "/" ? "" : pathname}`}</Text>Добавлено: <Spacer />Добавлено: </Box>Добавлено: <Box className="flex-row h-1 px-1 gap-3">Добавлено: <Link href="/" shortcut="1">Overview</Link>Добавлено: <Link href="/deployments" shortcut="2">Deployments</Link>Добавлено: <Link href="/settings" shortcut="3">Settings</Link>Добавлено: </Box>Добавлено: <Box className="flex-col grow p-1">{children}</Box>Добавлено: </Box>Добавлено: );Добавлено: }shortcut привязывает одну клавишу к ссылке. Нажмите 1, 2 и 3 в консоли; в реальном приложении URL менялся бы при каждом нажатии.
Возврат назад
useRouter() выполняет переходы из кода. Привяжите Backspace к router.back() в макете:
Удалено: import { Box, Spacer, Text } from "@textjs/app";Добавлено: import { Box, Spacer, Text, useInput } from "@textjs/app";import Link from "@textjs/app/link";Удалено: import { usePathname } from "@textjs/app/navigation";Добавлено: import { usePathname, useRouter } from "@textjs/app/navigation";export default function RootLayout({ children }: { children?: ReactNode }) { const pathname = usePathname();Добавлено: const router = useRouter();Добавлено: Добавлено: useInput((e) => {Добавлено: if (e.key === "backspace") router.back();Добавлено: });Динамические сегменты
Папки [id] получают своё значение в params:
import { Text, type PageProps } from "@textjs/app";export default function DeploymentPage({ params }: PageProps<{ id: string }>) { return <Text bold>{params.id}</Text>;}На статическом хостинге для таких динамических сегментов нужно правило перезаписи на index.html. Это рассматривается в главе 10.
Попробовать
Это Acme Deploys в конце главы, работающее в DevTools. Нажмите на панель, затем используйте клавиши ниже.
Открыть консоль
Приложение рендерится в DevTools.Сначала включите «Показывать функции для веб-разработчиков» в Safari: «Настройки» → «Дополнения». Затем щёлкните здесь и нажмите 2.
Открыть на компьютере
Это приложение рендерится в консоли DevTools, для которой нужен браузер на компьютере.
Тест
2 вопросаОтветьте на все вопросы, чтобы завершить главу.