SolidJS router template

Solid Router https://docs.solidjs.com/solid-router/ card image

Solid Router支持基于配置的路由和组件路由,使用哪种方式全看个人喜好

项目结构

初始化一个项目,使用 pnpm add @solidjs/router 下载依赖,精简项目结构,src目录下只有这几个文件,其中Hello.tsx用来演示延迟加载

1
2
3
4
5
src
├── App.tsx
├── env.d.ts
├── NotFound.tsx
└── index.tsx
1
2
3
4
5
import type { JSX } from "solid-js";

export default function NotFound(): JSX.Element {
  return <div>PageNotFound</div>;
}

基于配置的路由

下面代码中通过 * 定义404页面并演示延迟加载。

通过 routes定义路由,注意跟路由的组件 Layout 作为布局组件,可以添加 HeaderFooter,然后只切换中间区域

如果没有第一个子路由,直接访问 / 会发现找不到任何路由

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import {
  Router,
  type RouteDefinition,
  type RouteSectionProps,
} from "@solidjs/router";
import type { JSX, JSXElement } from "solid-js";
import { lazy } from "solid-js";
import { render } from "solid-js/web";

function Layout(props: RouteSectionProps): JSXElement {
  return (
    <>
      <header>header</header>
      <hr />
      {props.children}
      <hr />
      <footer>footer</footer>
    </>
  );
}

const root = document.getElementById("root");
if (!root) {
  throw new Error("root not found");
}

function Child2(): JSX.Element {
  return <div>Child2</div>;
}

function Child1(): JSX.Element {
  return <div> Child1</div>;
}

function Main(): JSXElement {
  return <div>Main</div>;
}

const routes: RouteDefinition[] = [
  {
    path: "/",
    component: Layout,
    children: [
      {
        path: "",
        component: Main,
      },
      {
        path: "/child1",
        component: Child1,
      },
      {
        path: "/child2",
        component: Child2,
      },
    ],
  },
  {
    path: "*",
    component: lazy(() => import("./NotFound")),
  },
];

render(() => <Router children={routes} />, root);

组件路由

组件路由和基于配置的路由区别不大,想访问根路由依然需要定义高亮的那行路由

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import { Route, Router, type RouteSectionProps } from "@solidjs/router";
import type { JSXElement } from "solid-js";
import { render } from "solid-js/web";
import NotFound from "./NotFound.tsx";

function Layout(props: RouteSectionProps): JSXElement {
  return (
    <>
      <header>header</header>
      <hr />
      {props.children}
      <hr />
      <footer>footer</footer>
    </>
  );
}

const root = document.getElementById("root");
if (!root) {
  throw new Error("root not found");
}

function Child2(): JSXElement {
  return <div>Child2</div>;
}

function Child1(): JSXElement {
  return <div> Child1</div>;
}

function Main(): JSXElement {
  return <div>Main</div>;
}

function RouterComponent(): JSXElement {
  return (
    <Router>
      <Route path="/" component={Layout}>
        <Route path="/" component={Main} />
        <Route path="child1" component={Child1} />
        <Route path="child2" component={Child2} />
      </Route>

      <Route path="*" component={NotFound} />
    </Router>
  );
}

render(RouterComponent, root);

提示

官网还展示了根级布局,下面演示一下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import { Route, Router } from "@solidjs/router";
import { type JSX, type JSXElement } from "solid-js";
import { render } from "solid-js/web";

const root = document.getElementById("root");
if (!root) {
  throw new Error("root not found");
}

function Home(): JSX.Element {
  return <div>"Home"</div>;
}
function About(): JSX.Element {
  return <div>"About"</div>;
}

function Layout(props: { children?: JSXElement }): JSXElement {
  return (
    <>
      <header>Header</header>
      {props.children}
      <footer>Footer</footer>
    </>
  );
}

function RouterComponent(): JSXElement {
  return (
    <Router root={Layout}>
      <Route path="/" component={Home} />
      <Route path="/about" component={About} />
    </Router>
  );
}

render(() => <RouterComponent />, root);

路径参数

使用 Typescript 声明 useParams 的泛型类型时,需要在 interface 类型定义中添加 第13行

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { Route, Router, useParams } from "@solidjs/router";
import { type JSXElement } from "solid-js";
import { render } from "solid-js/web";

const root = document.getElementById("root");
if (!root) {
  throw new Error("root not found");
}

function Child2(): JSXElement {
  interface Param {
    id: string;
    [key: string]: string;
  }
  const param = useParams<Param>();
  return <>{param.id}</>;
}

function RouterComponent(): JSXElement {
  return (
    <Router>
      <Route path="/">
        <Route path="child2/:id" component={Child2} />
      </Route>
    </Router>
  );
}

render(() => <RouterComponent />, root);