我正在尝试构建一个 Next.js 应用程序来显示按类别和子类别组织的产品目录。类别和子类别数据存储在一个对象数组中,如下所示:
const categories = [
{
id: 1,
name: "Category A",
subcategories: [
{
id: 1,
name: "Subcategory A1",
subsubcategories: [
{
id: 1,
name: "Sub-Subcategory A1.1",
},
{
id: 2,
name: "Sub-Subcategory A1.2",
},
],
},
{
id: 2,
name: "Subcategory A2",
subsubcategories: [
{
id: 3,
name: "Sub-Subcategory A2.1",
},
{
id: 4,
name: "Sub-Subcategory A2.2",
},
],
},
],
},
{
id: 2,
name: "Category B",
subcategories: [
{
id: 3,
name: "Subcategory B1",
subsubcategories: [
{
id: 5,
name: "Sub-Subcategory B1.1",
},
{
id: 6,
name: "Sub-Subcategory B1.2",
},
],
},
{
id: 4,
name: "Subcategory B2",
subsubcategories: [
{
id: 7,
name: "Sub-Subcategory B2.1",
},
{
id: 8,
name: "Sub-Subcategory B2.2",
},
],
},
],
},
];
我希望能够为遵循模式类别/子类别/子子类别/产品 ID 的每个产品生成动态路径。例如,如果用户单击类别 A、子类别 A1 和子子类别 A1.1 中 ID 为 123 的产品,则 URL 应如下所示:/category-a/subcategory-a1/sub-subcategory-a1- 1/123.
产品数据存储在一个单独的对象数组中,如下所示:
const products = [
{
id: 123,
name: "Product A1.1.1",
category_id: 1,
subcategory_id: 1,
subsubcategory_id: 1,
description: "Lorem ipsum dolor sit amet",
price: 9.99,
image: "/images/product-a1-1-1.jpg",
},]
category-a/subcategory-a1/sub-subcategory-a1-1/123.
试试这个:
// 文件:
/pages/[category]/[subcategory]/[subsubcategory]/[product].js
import React from 'react'
import { useRouter } from 'next/router'
const items = [
{
id: 1,
name: "Banana",
category: 1,
subcategory: 1,
subsubcategory: 1,
},
{
id: 2,
name: "Foobar",
category: 2,
subcategory: 3,
subsubcategory: 5,
}
];
const categories = [
{
id: 1,
name: "Fruits",
subcategories: [
{
id: 1,
name: "Tropical fruits",
subsubcategories: [
{
id: 1,
name: "Berry fruits", // yes a banana is really a berry fruit
},
{
id: 2,
name: "Sub-Subcategory A1.2",
},
],
},
{
id: 2,
name: "Subcategory A2",
subsubcategories: [
{
id: 3,
name: "Sub-Subcategory A2.1",
},
{
id: 4,
name: "Sub-Subcategory A2.2",
},
],
},
],
},
{
id: 2,
name: "Category B",
subcategories: [
{
id: 3,
name: "Subcategory B1",
subsubcategories: [
{
id: 5,
name: "Sub-Subcategory B1.1",
},
{
id: 6,
name: "Sub-Subcategory B1.2",
},
],
},
{
id: 4,
name: "Subcategory B2",
subsubcategories: [
{
id: 7,
name: "Sub-Subcategory B2.1",
},
{
id: 8,
name: "Sub-Subcategory B2.2",
},
],
},
],
},
];
const slugify = str =>
str
.toLowerCase()
.trim()
.replace(/[^\w\s-]/g, '')
.replace(/[\s_-]+/g, '-')
.replace(/^-+|-+$/g, '');
export default function Product() {
const router = useRouter()
const { category, subcategory, subsubcategory, product } = router.query
console.log(category, subcategory, subsubcategory, product);
// {category: 'fruits', subcategory: 'tropical-fruits', subsubcategory: 'berry-fruits', product: 'banana'}
const found = items.find((item) => slugify(item.name) === product); // banana === banana
console.log({ found });
// {id: 1, name: 'Banana', category: 1, subcategory: 1, subsubcategory: 1}
return (
<div>{found.name}</div>
)
}
export async function getStaticPaths() {
const paths = items.map((item) => {
// find the right categories for this product item
let categoryFound = categories.find((c) => c.id == item.category);
let subcategoryFound = categoryFound.subcategories.find((sc) => sc.id == item.subcategory);
let subsubcategoryFound = subcategoryFound.subsubcategories.find((ssc) => ssc.id == item.subsubcategory);
return {
params: {
product: slugify(item.name), // the slug
category: slugify(categoryFound.name),
subcategory: slugify(subcategoryFound.name),
subsubcategory: slugify(subsubcategoryFound.name)
}
}
});
return {
paths,
fallback: false,
};
}
export async function getStaticProps({ params }) {
const { category, subcategory, subsubcategory, product } = params;
return {
props: {
category,
subcategory,
subsubcategory,
product,
},
};
}
构建过程还构建了具有正确类别的产品页面: 图片
你可以像这样打开你的产品:
http://localhost:3000/fruits/tropical-fruits/berry-fruits/banana
基本理念:
在 NextJs 构建之前生成
pages/
或 app/
页面(准备脚本)
想太多的嵌套结构:subsubsub 没那么通用,万一哪天多出 3 个子类呢?无论如何,你保存一些代码并使用递归使其更具可读性......
顺便说一句,我想我要给 NextJS 准备提案,它真的有点缺失.. 页面应该像那样生成。
// Proposal: consider this article structure… dev’s love flattened structures
const articles = [
id: 1,
name: “banana”,
category: [1, 1, 1]
];
// some pseudo code to let you start already. BTW just call them ‘categories’ in nesting if possible. ask backend, otherwise map it yourself (use a generator function instead of map if many articles to avoid memory overconsumption) I dislike the fact that category and subCategory can have same id, id’s should be unique in the whole app, hard to get a category/subcategory by id otherwise (or redundant code and complications on later usecases. should still work having `id: 1` everywhere:
const categories = [
id: 1,
name: “fruits”,
categories: [
{
id: 1,
name: “berry fruits”,
categories: [
{
id: 1,
name: “small berries lol” // 🍓🫐
}
]
}
]
];
// get paths to generate (deepest nesting)
function recursive(category, currentPath=“”){
return category.categories
? recursive(category.categories,`$(currentPath}/[${category.name}]`)
: category(`${currentPath}/[${category.name}]/`;
});
const paths = recursive(categories);
});
// create dynamic folder structure
// could be done in ‘recursive else’ too (faster)
paths.forEach((path) => {
mkdirp.sync(path); // install 📦 first
});
// then articles…
// I am writing all of this on my mobile device, will enhance later, hope you get an idea of the approach I’m suggesting meanwhile
让我知道你在做什么,将在真实设备上继续 😉
currentPath的参数有一个错误,稍后编辑