全书目录

第三十一篇:Remix 完全指南 —— Web 原生航运港宇宙

八、嵌套路由:一座港区里还有子码头

1 分钟 160 字 第 571 / 962 个阅读单元

Remix 很强的一点,是布局、数据和 URL 可以一起嵌套。

例如你有这样的结构:

tsx
// app/routes/ships.tsx
import { Outlet, useLoaderData, NavLink } from "@remix-run/react";
import { json } from "@remix-run/node";
import { getShipStats } from "~/models/ship.server";

export async function loader() {
  return json({ stats: await getShipStats() });
}

export default function ShipsLayout() {
  const { stats } = useLoaderData<typeof loader>();

  return (
    <div>
      <header>
        <h1>船舶港区</h1>
        <p>今日在港:{stats.inPort}</p>
        <nav>
          <NavLink to=".">总览</NavLink>
          <NavLink to="new">新建船舶</NavLink>
        </nav>
      </header>

      <section>
        <Outlet />
      </section>
    </div>
  );
}

再配上:

tsx
// app/routes/ships._index.tsx
import { useLoaderData } from "@remix-run/react";
import { json } from "@remix-run/node";
import { listShips } from "~/models/ship.server";

export async function loader() {
  return json({ ships: await listShips() });
}

export default function ShipsIndexRoute() {
  const { ships } = useLoaderData<typeof loader>();

  return (
    <ul>
      {ships.map((ship) => (
        <li key={ship.id}>{ship.name}</li>
      ))}
    </ul>
  );
}

这时候页面结构就是:

text
root
└── ships.tsx               船舶港区公共框架
    └── ships._index.tsx    船舶列表区

用户在 /ships/ships/new 之间切换时,父布局可以不重建,只有子泊位在变。

这就是 Remix 的一个关键性能来源:

不是每次整页重来,而是知道哪一层港区还在,哪一层才需要重新靠港。