Next.js电商项目中点击商品图片跳转详情页自动渲染对应内容实现问询
实现方案
1. 先创建Next.js动态路由详情页
Next.js的动态路由可以根据商品ID复用同一个详情页组件,完全不需要硬编码每个商品的页面。
在pages目录下创建pages/product/[id].js文件(如果用App Router的话就创建app/product/[id]/page.js),这个就是通用的商品详情页。
2. 修改Items组件的跳转逻辑
把原来跳转到固定/Description的逻辑改成携带当前商品ID跳转:
// 把img标签的onClick改成如下 <img onClick={() => router.push(`/product/${id}`)} src={image} height={400} width={400} objectFit="contain" className="cursor-pointer" alt={name} />
如果你的Next.js版本用的是App Router,替换成useRouter从'next/navigation'导入即可。
3. 详情页获取商品数据并渲染
首先调整你的商品数据源结构,每个商品增加多图字段images用来存不同角度的轮播图,示例结构:
// 你的products数组里的单个商品结构示例 { id: 1, name: "纯棉牛津纺衬衫", price: 99, size: "M/L/XL", image: "https://xxx.com/main.jpg", // 列表页主图 images: [ // 详情页轮播图数组 "https://xxx.com/main.jpg", "https://xxx.com/side.jpg", "https://xxx.com/back.jpg", "https://xxx.com/detail.jpg" ], desc: "100%纯棉,亲肤透气,百搭款" }
然后写通用详情页代码(Pages Router版本示例):
import { useRouter } from "next/router"; import Image from "next/image"; import products from "../../product/MenShoes/MenShoes"; // 导入你的商品数据源 import Carousel from "../../components/Carousel"; // 后面会写通用轮播组件 export default function ProductDetail() { const router = useRouter(); const { id } = router.query; // 匹配当前点击的商品数据 const currentProduct = products.find(item => item.id === Number(id)); if (!currentProduct) return <div>商品不存在</div>; return ( <div className="max-w-7xl mx-auto p-5"> <div className="grid md:grid-cols-2 gap-10"> {/* 轮播图区域 */} <Carousel images={currentProduct.images} /> {/* 商品信息区域 */} <div> <h1 className="text-2xl font-bold mb-3">{currentProduct.name}</h1> <p className="text-xl text-red-500 mb-3">${currentProduct.price}</p> <p className="mb-3">尺码:{currentProduct.size}</p> <p className="mb-5">{currentProduct.desc}</p> <button className="button">加入购物车</button> </div> </div> </div> ) }
4. 封装通用轮播组件
创建components/Carousel.js文件,通用接收images数组参数即可,不需要硬编码任何图片:
import { useState } from "react"; import Image from "next/image"; export default function Carousel({ images }) { const [currentIndex, setCurrentIndex] = useState(0); const prev = () => { setCurrentIndex(prev => prev === 0 ? images.length - 1 : prev - 1); }; const next = () => { setCurrentIndex(prev => prev === images.length - 1 ? 0 : prev + 1); }; return ( <div className="relative w-full h-[500px]"> <Image src={images[currentIndex]} fill objectFit="contain" alt="商品展示图" /> <button onClick={prev} className="absolute left-2 top-1/2 -translate-y-1/2 bg-white/80 w-8 h-8 rounded-full">←</button> <button onClick={next} className="absolute right-2 top-1/2 -translate-y-1/2 bg-white/80 w-8 h-8 rounded-full">→</button> {/* 底部小点点指示器 */} <div className="absolute bottom-2 left-1/2 -translate-x-1/2 flex gap-2"> {images.map((_, index) => ( <span key={index} onClick={() => setCurrentIndex(index)} className={`w-2 h-2 rounded-full cursor-pointer ${index === currentIndex ? 'bg-black' : 'bg-gray-300'}`} /> ))} </div> </div> ) }
这样所有商品共用这一套组件,后续新增商品只需要在products数组里加对应数据即可,不需要修改任何组件代码。
内容的提问来源于stack exchange,提问作者juwie
相关产品推荐
相关产品推荐

