QWIK DOCS / V2

文件路由

用目录与 index 文件描述 URL,页面、端点与布局各司其职。

约 4 分钟Qwik v211 / 19
本页目录5 节
  1. 三种文件,三种职责
  2. 动态路由
  3. 路由优先级
  4. 布局
  5. SPA 导航

Qwik Router 是文件系统路由:src/routes 下的目录与文件直接决定 URL 结构。你不需要维护一张路由表,新增页面就是新增文件。

textsrc/routes 目录
src/
└── routes/
    ├── layout.tsx              # 根布局
    ├── index.tsx               # /
    ├── about/
    │   └── index.tsx           # /about
    ├── blog/
    │   ├── layout.tsx          # /blog/* 的布局
    │   ├── index.tsx           # /blog
    │   └── [slug]/
    │       └── index.tsx       # /blog/hello-world
    ├── api/
    │   └── stats/
    │       └── index.ts        # JSON 端点
    └── [...missing]/
        └── index.tsx           # 兜底页面

01三种文件,三种职责#

文件职责返回
index.tsx页面组件渲染后的 HTML
index.tsHTTP 端点JSON、文本或其他响应
layout.tsx共享 UI 与中间件包含 <Slot /> 的页面
tsxsrc/routes/about/index.tsx
import { component$ } from '@qwik.dev/core';

export default component$(() => {
  return <h1>关于我们</h1>;
});

index.ts 不导出组件,而是导出 onGet、onPost 等请求处理函数。它适合 REST 接口、Webhook 与文件下载。

tsxsrc/routes/api/stats/index.ts
import type { RequestHandler } from '@qwik.dev/router';

export const onGet: RequestHandler = ({ json }) => {
  json(200, { online: true });
};

02动态路由#

方括号目录表示动态段。[slug] 匹配一个路径段,[...all] 匹配剩余所有段,参数从 useLocation() 的 params 读取。

tsxsrc/routes/blog/[slug]/index.tsx
import { component$ } from '@qwik.dev/core';
import { useLocation } from '@qwik.dev/router';

export default component$(() => {
  const loc = useLocation();
  return <h1>文章:{loc.params.slug}</h1>;
});
文件匹配的 URLparams
routes/user/[username]/index.tsx/user/foo{ username: 'foo' }
routes/post/[...all]/index.tsx/post/2026/11/qwik{ all: '2026/11/qwik' }
routes/shop/[category]/[id]/index.tsx/shop/book/42{ category: 'book', id: '42' }

03路由优先级#

多条路由同时匹配时,Qwik Router 从左到右逐段比较:静态段优先于 [param],[param] 优先于 [...catchAll]。目录顺序与括号分组不影响结果。

textcode
/pricing                      → pricing/index.tsx
/news/feed.xml                → [section]/feed.xml/index.ts
/news/today                   → [section]/[topic]/index.tsx
/acme/settings/billing        → [org]/[...path]/index.tsx

04布局#

layout.tsx 同时承担两件事:包裹子路由的 UI,以及在渲染前执行的中间件。子页面通过 <Slot /> 插入布局内容。

tsxsrc/routes/layout.tsx
import { component$, Slot } from '@qwik.dev/core';

export default component$(() => {
  return (
    <div class="shell">
      <header>Qwik 中文站点</header>
      <main>
        <Slot />
      </main>
    </div>
  );
});

布局可以嵌套,请求也会逐层经过每一级的 onRequest。例如 /admin/users 会依次执行根布局、admin/layout.tsx、页面自身的处理函数。

05SPA 导航#

<Link> 渲染一个真正的 <a> 标签:没有 JavaScript 时是普通页面跳转,有 JavaScript 时升级为 SPA 导航。优先使用它,而不是在按钮里手写跳转。

tsxcode
import { component$ } from '@qwik.dev/core';
import { Link, useNavigate } from '@qwik.dev/router';

export default component$(() => {
  const nav = useNavigate();
  return (
    <nav>
      <Link href="/docs/">文档</Link>
      <button onClick$={() => nav('/about')}>关于</button>
    </nav>
  );
});
写法行为
<Link href="/docs/">可访问的页面跳转,支持预取
<Link reload>重新执行当前路由的 loader 并刷新
useNavigate()('/path')在代码中触发导航
useNavigate()()刷新当前页面

<Link> 默认在链接进入视口时预取路由代码,在用户表现出点击意图时预取数据。滚动位置由浏览器 history 恢复,刷新、前进后退都不会闪动。