路径参数用于匹配单个段(直到下一个 / 的文本)并将其值作为命名变量返回给您。它们通过在路径中使用 $ 字符前缀定义,后跟要分配给它的键变量。以下是有效的路径参数路径:
因为路径参数路由只匹配到下一个 /,所以可以创建子路由来继续表达层次结构:
让我们创建一个使用路径参数匹配帖子 ID 的帖子路由文件:
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => {
return fetchPost(params.postId)
},
})
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => {
return fetchPost(params.postId)
},
})
一旦路径参数被解析,它就可以被所有子路由使用。这意味着如果我们为 postRoute 定义一个子路由,我们可以在子路由的路径中使用来自 URL 的 postId 变量!
路径参数作为 params 对象传递给加载器。此对象的键是路径参数的名称,值是从实际 URL 路径中解析出的值。例如,如果我们访问 /blog/123 URL,params 对象将是 { postId: '123' }:
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => {
return fetchPost(params.postId)
},
})
export const Route = createFileRoute('/posts/$postId')({
loader: async ({ params }) => {
return fetchPost(params.postId)
},
})
params 对象也会传递给 beforeLoad 选项:
export const Route = createFileRoute('/posts/$postId')({
beforeLoad: async ({ params }) => {
// do something with params.postId
},
})
export const Route = createFileRoute('/posts/$postId')({
beforeLoad: async ({ params }) => {
// do something with params.postId
},
})
如果我们向 postRoute 添加组件,我们可以通过使用路由的 useParams 钩子从 URL 访问 postId 变量:
export const Route = createFileRoute('/posts/$postId')({
component: PostComponent,
})
function PostComponent() {
const { postId } = Route.useParams()
return <div>Post {postId}</div>
}
export const Route = createFileRoute('/posts/$postId')({
component: PostComponent,
})
function PostComponent() {
const { postId } = Route.useParams()
return <div>Post {postId}</div>
}
🧠 快速提示:如果您的组件是代码分割的,您可以使用 getRouteApi 函数 来避免必须导入 Route 配置以获得对类型化 useParams() 钩子的访问。
您还可以使用全局导出的 useParams 钩子从应用程序中的任何组件访问任何已解析的路径参数。您需要向 useParams 传递 strict: false 选项,表示您想要从模糊位置访问参数:
function PostComponent() {
const { postId } = useParams({ strict: false })
return <div>Post {postId}</div>
}
function PostComponent() {
const { postId } = useParams({ strict: false })
return <div>Post {postId}</div>
}
当导航到带有路径参数的路由时,TypeScript 将要求您将参数作为对象或作为返回参数对象的函数传递。
让我们看看对象样式是什么样的:
function Component() {
return (
<Link to="/blog/$postId" params={{ postId: '123' }}>
Post 123
</Link>
)
}
function Component() {
return (
<Link to="/blog/$postId" params={{ postId: '123' }}>
Post 123
</Link>
)
}
这是函数样式的样子:
function Component() {
return (
<Link to="/blog/$postId" params={(prev) => ({ ...prev, postId: '123' })}>
Post 123
</Link>
)
}
function Component() {
return (
<Link to="/blog/$postId" params={(prev) => ({ ...prev, postId: '123' })}>
Post 123
</Link>
)
}
请注意,当您需要保留 URL 中已存在的其他路由参数时,函数样式很有用。这是因为函数样式将接收当前参数作为参数,允许您根据需要修改它们并返回最终的参数对象。
默认情况下,路径参数使用 encodeURIComponent 进行转义。如果您想允许其他有效的 URI 字符(例如 @ 或 +),您可以在 RouterOptions 中指定。
使用示例:
const router = createRouter({
...
pathParamsAllowedCharacters: ['@']
})
const router = createRouter({
...
pathParamsAllowedCharacters: ['@']
})
以下是接受的允许字符列表: ; : @ & = + $ ,