Next.js动态路由结构搭建求助(TypeScript环境)
Next.js + TypeScript 动态路由实现方案
目录结构设计
Pages Router(Next.js 12及以下,适合新手入门)
pages/ ├── index.tsx # 主域名首页(匹配 /) ├── [chain].tsx # 匹配 /eth 这类单参数路径 └── [chain]/ └── [dexOrToken].tsx # 匹配 /eth/uni 或 /eth/0xr83urt36sdt45t
App Router(Next.js 13+ 推荐方案)
app/ ├── page.tsx # 主域名首页(匹配 /) └── [chain]/ ├── page.tsx # 匹配 /eth 这类单参数路径 └── [dexOrToken]/ └── page.tsx # 匹配 /eth/uni 或 /eth/0xr83urt36sdt45t
核心路由逻辑
Next.js 通过[]包裹参数名实现动态路由匹配:
- 根路径
/→ 对应首页组件 /[chain]→ 匹配任意单层级路径,参数chain自动传递到对应组件/[chain]/[dexOrToken]→ 匹配二级路径,通过参数特征(比如是否以0x开头)区分是DEX名称还是Token地址,无需拆分两个独立路由
页面组件实现示例
Pages Router 版本
1. [chain].tsx(单参数页面)
import { useRouter } from 'next/router'; import type { NextPage } from 'next'; const ChainPage: NextPage = () => { const router = useRouter(); const { chain } = router.query; // 此处根据chain调用API加载链相关数据 return ( <div> <h1>当前链:{chain}</h1> {/* 渲染链对应内容 */} </div> ); }; export default ChainPage;
2. [chain]/[dexOrToken].tsx(二级参数页面)
import type { GetServerSideProps, NextPage } from 'next'; // 定义组件props类型 interface DetailProps { chain: string; contentData: { address?: string; name?: string; // 补充你的实际数据字段 }; isToken: boolean; } const ChainDetailPage: NextPage<DetailProps> = ({ chain, contentData, isToken }) => { return ( <div> <h1>当前链:{chain}</h1> {isToken ? ( <section> <h2>Token详情</h2> <p>地址:{contentData.address}</p> {/* 渲染Token相关内容 */} </section> ) : ( <section> <h2>DEX详情</h2> <p>名称:{contentData.name}</p> {/* 渲染DEX相关内容 */} </section> )} </div> ); }; // 服务器端获取数据(SEO友好) export const getServerSideProps: GetServerSideProps<DetailProps> = async (context) => { const { chain, dexOrToken } = context.params as { chain: string; dexOrToken: string }; const isToken = dexOrToken.startsWith('0x'); // 根据参数类型请求对应API const apiUrl = isToken ? `你的API地址/tokens/${chain}/${dexOrToken}` : `你的API地址/dexs/${chain}/${dexOrToken}`; const res = await fetch(apiUrl); const contentData = await res.json(); return { props: { chain, contentData, isToken } }; }; export default ChainDetailPage;
App Router 版本(Next.js 13+)
[chain]/[dexOrToken]/page.tsx(服务器组件,自动SSR)
// 默认是服务器组件,无需标记'use client' export default async function ChainDetailPage({ params }: { params: { chain: string; dexOrToken: string } }) { const { chain, dexOrToken } = params; const isToken = dexOrToken.startsWith('0x'); // 直接在组件内请求API(服务器端执行) const apiUrl = isToken ? `你的API地址/tokens/${chain}/${dexOrToken}` : `你的API地址/dexs/${chain}/${dexOrToken}`; const res = await fetch(apiUrl, { cache: 'no-store' }); // 禁用缓存,保证实时数据 const contentData = await res.json(); return ( <div> <h1>当前链:{chain}</h1> {isToken ? ( <section> <h2>Token详情</h2> <p>地址:{contentData.address}</p> </section> ) : ( <section> <h2>DEX详情</h2> <p>名称:{contentData.name}</p> </section> )} </div> ); }
关键注意事项
- 参数区分逻辑:通过
0x前缀判断Token地址是简单可行的方案,若有特殊情况可结合API校验(比如请求Token接口返回404则判定为DEX) - TypeScript类型:尽量避免使用
any,为API返回数据定义接口类型,提升代码健壮性 - 数据加载策略:服务器端渲染(SSR)适合需要SEO的场景,客户端渲染(CSR)适合交互性强的页面,可根据需求选择
内容的提问来源于stack exchange,提问作者Skinsky Gnudy
相关产品推荐
相关产品推荐

