框架
版本

路径参数

路径参数用于匹配单个片段(直到下一个 / 之前的文本),并将其值作为命名变量返回给您。它们通过在路径中使用 $ 字符前缀来定义,后跟要分配给它的键变量。以下是有效的路径参数路径

  • $postId
  • $name
  • $teamId
  • about/$name
  • team/$teamId
  • blog/$postId

由于路径参数路由仅匹配到下一个 /,因此可以创建子路由以继续表达层级结构

让我们创建一个帖子路由文件,该文件使用路径参数来匹配帖子 ID

  • posts.$postId.tsx
tsx
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 变量!

Loader 中的路径参数

路径参数作为 params 对象传递给 loader。此对象的键是路径参数的名称,值是从实际 URL 路径中解析出来的值。例如,如果我们访问 /blog/123 URL,则 params 对象将是 { postId: '123' }

tsx
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 选项

tsx
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 hook 从 URL 访问 postId 变量

tsx
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() hook。

路由外的路径参数

你还可以使用全局导出的 useParams hook 来访问应用程序中任何组件的任何已解析的路径参数。你需要将 strict: false 选项传递给 useParams,表示你想从一个不明确的位置访问参数

tsx
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 将要求你将参数作为对象或返回参数对象的函数传递。

让我们看看对象样式是什么样的

tsx
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>
  )
}

这是函数样式的样子

tsx
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 中指定它

用法示例

tsx
const router = createRouter({
  ...
  pathParamsAllowedCharacters: ['@']
})
const router = createRouter({
  ...
  pathParamsAllowedCharacters: ['@']
})

以下是接受的允许字符列表: ; : @ & = + $ ,

订阅 Bytes

您的每周 JavaScript 新闻。每周一免费发送给超过 100,000 名开发者。

Bytes

无垃圾邮件。随时取消订阅。