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

Next.js 13页面内嵌套路由组件:无跳转切换产品分类方案问询

在Next.js 13中实现带分类子导航的产品概览页面

要实现点击分类子导航切换内容、更新URL但不跳转页面的效果,核心是利用Next.js的客户端路由能力结合动态路由,下面是具体实现步骤:

1. 规划路由结构

给不同分类设置独立路由,比如:

  • 男装:/products/men
  • 女装:/products/women
  • 全部商品:/products

在App Router目录下创建如下结构:

app/
├─ products/
│  ├─ [category]/
│  │  └─ page.js
│  ├─ layout.js
│  └─ page.js

2. 编写布局组件(保持页面其他部分不变)

app/products/layout.js作为产品页的布局容器,放置头部、侧边栏等不需要随分类切换的内容,子内容会在children中渲染:

// app/products/layout.js
export default function ProductsLayout({ children }) {
  return (
    <div className="product-page-container">
      {/* 头部导航 */}
      <header>品牌商城</header>
      <main>{children}</main>
      {/* 页脚 */}
      <footer>版权信息</footer>
    </div>
  );
}

3. 实现分类子导航组件

创建客户端组件SubNavigation.js,使用useRouter和useParams实现点击切换路由、高亮当前分类:

// app/components/SubNavigation.js
'use client';

import { useRouter, useParams } from 'next/navigation';

const categories = [
  { name: '全部', slug: '' },
  { name: '男装', slug: 'men' },
  { name: '女装', slug: 'women' },
];

export default function SubNavigation() {
  const router = useRouter();
  const { category } = useParams();

  const handleCategoryClick = (slug) => {
    // 切换路由,不刷新页面
    const path = slug ? `/products/${slug}` : '/products';
    router.push(path);
  };

  return (
    <div className="sub-nav">
      {categories.map((item) => (
        <button
          key={item.slug}
          onClick={() => handleCategoryClick(item.slug)}
          className={`nav-item ${category === item.slug || (!category && item.slug === '') ? 'active' : ''}`}
        >
          {item.name}
        </button>
      ))}
    </div>
  );
}

4. 编写分类页面逻辑

  • 全部商品页面(app/products/page.js):
// app/products/page.js
import SubNavigation from '@/app/components/SubNavigation';
import ProductList from '@/app/components/ProductList';

// 获取全部商品数据
async function getAllProducts() {
  // 这里替换为实际的API请求或数据查询
  const res = await fetch('https://api.example.com/products');
  return res.json();
}

export default async function AllProductsPage() {
  const products = await getAllProducts();

  return (
    <div>
      <SubNavigation />
      <ProductList products={products} />
    </div>
  );
}
  • 分类商品页面(app/products/[category]/page.js):
// app/products/[category]/page.js
import SubNavigation from '@/app/components/SubNavigation';
import ProductList from '@/app/components/ProductList';

// 根据分类获取商品数据
async function getProductsByCategory(category) {
  // 这里替换为实际的API请求或数据查询
  const res = await fetch(`https://api.example.com/products?category=${category}`);
  return res.json();
}

export default async function CategoryProductsPage({ params }) {
  const products = await getProductsByCategory(params.category);

  return (
    <div>
      <SubNavigation />
      <ProductList products={products} />
    </div>
  );
}

5. 商品列表组件(通用)

创建ProductList.js负责渲染商品内容:

// app/components/ProductList.js
export default function ProductList({ products }) {
  return (
    <div className="product-grid">
      {products.map((product) => (
        <div key={product.id} className="product-card">
          <h3>{product.name}</h3>
          <p>¥{product.price}</p>
        </div>
      ))}
    </div>
  );
}

关键说明

  • 客户端路由:通过useRouter的push方法修改URL,Next.js会在客户端处理导航,不会刷新整个页面,布局组件保持不变。
  • 动态路由与参数:useParams获取当前分类参数,用于高亮子导航和请求对应分类的数据。
  • 服务端渲染:页面组件默认是服务端组件,可直接在组件内异步获取数据,保证首屏性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:04:55