You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js 14如何通过路由传参?保持URL为商品名称

解决方案

方案一:通过商品名称(Slug)在服务器端反查ID(推荐)

这是最稳妥的实现方式,URL中的商品名称(slug)本身就应该和商品一一对应,直接在目标页面的服务器组件里用slug查询数据库获取ID即可,无需额外传递:

  1. 将路由文件夹重命名为app/items/[slug]/page.js(把之前的[itemId]改成[slug]更语义化)
  2. 商品列表页面跳转时,直接用处理后的商品标题作为slug:
'use client';
import { useRouter } from 'next/navigation';

// 商品列表项组件
const ItemCard = ({ item }) => {
  const router = useRouter();
  // 处理标题为URL安全格式,避免特殊字符导致路由错误
  const safeTitle = encodeURIComponent(item.title);
  return (
    <div onClick={() => router.push(`/items/${safeTitle}`)}>
      {/* 商品内容渲染 */}
    </div>
  );
};
  1. 在app/items/[slug]/page.js服务器组件中,通过params.slug查询商品ID:
// 服务器组件,无需添加'use client'指令
export default async function ItemPage({ params }) {
  // 解码URL中的slug,还原原始标题
  const originalTitle = decodeURIComponent(params.slug);
  // 根据标题从数据库/API查询商品详情(包含ID)
  const item = await fetch(`https://your-api.com/items?title=${originalTitle}`).then(res => res.json());
  
  // 拿到ID后发起后续业务请求
  const relatedData = await fetch(`https://your-api.com/related/${item.id}`).then(res => res.json());
  
  return (
    <div>
      <h1>{item.title}</h1>
      {/* 商品详情及关联内容渲染 */}
    </div>
  );
}

方案二:通过导航State传递ID(客户端临时传递,不暴露URL)

如果必须在客户端直接传递ID,Next.js 14的useRouter支持跳转时传递state参数,该数据不会出现在URL中,仅在客户端导航流程中保留:

  1. 列表页面跳转时,附带state传递ID:
'use client';
import { useRouter } from 'next/navigation';

const ItemCard = ({ item }) => {
  const router = useRouter();
  const safeTitle = encodeURIComponent(item.title);
  return (
    <div 
      onClick={() => {
        router.push(`/items/${safeTitle}`, {
          state: { itemId: item.id }
        });
      }}
    >
      {/* 商品内容渲染 */}
    </div>
  );
};
  1. 在目标页面的客户端组件中,从路由state中获取ID:
'use client';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';

export default function ItemPage() {
  const router = useRouter();
  const [itemData, setItemData] = useState(null);

  useEffect(() => {
    // 从导航state中提取ID
    const navState = router.state;
    if (navState?.itemId) {
      // 用ID发起请求获取商品数据
      fetch(`https://your-api.com/items/${navState.itemId}`)
        .then(res => res.json())
        .then(data => setItemData(data));
    }
  }, [router]);

  if (!itemData) return <div>Loading...</div>;

  return (
    <div>
      <h1>{itemData.title}</h1>
      {/* 商品详情渲染 */}
    </div>
  );
}

注意:这种方式的state仅在客户端跳转时有效,如果用户直接刷新页面或通过URL访问,state会丢失,因此仅适合临时数据传递,优先推荐方案一。

内容的提问来源于stack exchange,提问作者andorando

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 21:57:56