Pages and Layouts#
We adopt page and layout capabilities based on file directory structure, which means you can use file directories to manage your pages and layouts.
In this chapter, we will provide a complete guide on how to create pages and layouts.
Creating Pages#
Pages are interface components displayed on specific routes. We define files ending with .page.tsx
as page files, and the route address is mapped according to the directory hierarchy structure where the page file is located.
Let's create our first page by creating an order
directory under the src/pages
directory, and then creating an Order.page.tsx
file to export a component.
// src/pages/order/Order.page.tsx export default function Order() { return <div>Order Page</div> }
It's worth noting that when the directory structure is finally mapped to route addresses, if the last directory name is index
, that part of the route address mapping will be automatically omitted.
Check out the following examples to help you understand this:
Page File Directory | Route Address |
---|---|
src/pages/index /Index.page.tsx | / |
src/pages/order/index /Order.page.tsx` | /order |
src/pages/ware/index/detail /Detail.page.tsx` | /ware/index/detail |
Dynamic Routes#
We can specify dynamic routes by adding brackets to directory names, such as [id]
.
Let's add a page file in the src/pages/order/[id]/detail
directory and export a component.
[id]
will be mapped as a dynamic parameter, and you can get the current parameter value using useParams()
.
// src/pages/order/[id]/detail/Detail.page.tsx import { useParams } from "wiscore/router" export default function Detail() { const { id } = useParams(); return <div>Order Detail id: {id}</div>; }
Creating Layouts#
Layouts are shared interface layouts between multiple pages, commonly used to implement common parts of a website, such as menu bars, navigation bars, user avatars, etc. The layouts here are different from layout systems in other frameworks. To achieve the feature of quick adaptation to multiple scenarios, we reflect layouts in route addresses. Changing the route address can quickly switch layouts, which becomes very convenient when applications need to be displayed with different layouts in different scenarios.
We define files ending with .layout.tsx
as layout files, and the direct parent directory of the layout file will be mapped as the layout route.
If your project doesn't already have a src/layouts
directory, please create it first. This directory will serve as a unified directory for storing all layouts. Next, we'll create the first layout by creating an index
directory in that directory, and creating an Index.layout.tsx
file to export a component.
// src/layouts/index/Index.layout.tsx export default function IndexLayout({ children }) { return ( <main> <header>App Header</header> {children} </main> ); }
When you want to access the previously created order
page with index
as the layout, simply access the address /index/order
.
With this capability, you can write multiple layouts for your project and access different layouts in different pages and scenarios.
Check out the following examples to fully understand how layouts are mapped:
Layout File Directory | Layout Route |
---|---|
src/layouts/index /Index.layout.tsx | /index |
src/layouts/container/column /Column.layout.tsx | /column |
From the examples above 👆, we can see that the layout route only recognizes the first-level parent directory. Folder nesting only provides a way to manage and categorize layouts.
Route Composition#
In addition to reflecting the pages
, layouts
, and parameters
described above, route addresses also reflect a type of route segment, which is the application. We won't introduce the concept of applications in this chapter, but since route-related APIs will involve applications, we briefly mention it. Once you've completed the application chapter, it will be easy to understand.
Route Switching#
We provide several commonly used route operation APIs that enable quick route switching.
import { useNavigate } from "wiscore/router"; function () { const navigate = useNavigate(); return ( <button onClick={() => navigate("/order")}> Navigate to order page </button> ); }
And they all follow the same set of switching rules:
- When the address about to be switched doesn't contain application and layout paths, it will automatically take the application and layout paths from the current address
- When the address about to be switched contains an application path, it will automatically take the layout path from the current address
- When the address about to be switched contains a layout path, the current layout and application become invalid.