React JS 博客列表及详情页路由跳转结构实现咨询
React博客列表+详情页技术结构设计方案
1. 前置依赖
我们用React Router v6实现路由跳转,先执行安装命令:npm install react-router-dom
2. 数据层规范约定
- 首先统一
blog-database.ts的字段结构,每个列表项必须携带唯一的详情页路径字段detailUrl,示例如下:
// blog-database.ts export interface BlogListItem { id: string | number; title: string; coverImg: string; summary: string; detailUrl: string; // 示例值:/blog/react-intro publishDate: string; } // 列表数据 export const blogListData: BlogListItem[] = [ { id: 1, title: "React入门教程", coverImg: "/xxx.png", summary: "本文讲解React基础用法", detailUrl: "/blog/react-intro", publishDate: "2024-05-20" }, // 其他列表项 ]
- 然后
blog-detail-database.ts采用路径做key的映射结构,方便快速匹配详情数据:
// blog-detail-database.ts export interface BlogDetailType { id: string | number; title: string; content: string; author: string; publishDate: string; tags: string[]; } // 路径为key的详情映射表 export const blogDetailMap: Record<string, BlogDetailType> = { "/blog/react-intro": { id: 1, title: "React入门教程", content: "<p>React是用于构建用户界面的JS库...</p>", author: "技术小编", publishDate: "2024-05-20", tags: ["前端", "React"] }, // 其他详情数据 }
3. 全局路由配置
只需要配置两条路由,即可覆盖所有列表和详情场景:
// App.tsx import { BrowserRouter, Routes, Route } from "react-router-dom"; import BlogList from "./pages/BlogList"; import BlogDetail from "./components/BlogDetail"; function App() { return ( <BrowserRouter> <Routes> {/* 博客列表页路由 */} <Route path="/blog" element={<BlogList />} /> {/* 详情页动态路由,匹配所有/blog/开头的路径 */} <Route path="/blog/*" element={<BlogDetail />} /> </Routes> </BrowserRouter> ); } export default App;
4. 组件实现
4.1 BlogCard1组件
点击「Continue Reading」按钮时跳转到对应详情路径:
// components/BlogCard1.tsx import { useNavigate } from "react-router-dom"; import { BlogListItem } from "../blog-database"; interface BlogCardProps { item: BlogListItem; } export default function BlogCard1({ item }: BlogCardProps) { const navigate = useNavigate(); return ( <div className="blog-card"> <img src={item.coverImg} alt={item.title} /> <h3>{item.title}</h3> <p className="summary">{item.summary}</p> <p className="date">{item.publishDate}</p> <button onClick={() => navigate(item.detailUrl)}>Continue Reading</button> </div> ); }
4.2 可复用BlogDetail组件
仅用这一个组件适配所有详情页,通过当前路径匹配对应数据:
// components/BlogDetail.tsx import { useLocation } from "react-router-dom"; import { blogDetailMap } from "../blog-detail-database"; export default function BlogDetail() { const { pathname } = useLocation(); const currentDetail = blogDetailMap[pathname]; // 没有匹配到数据时显示404提示 if (!currentDetail) { return <div className="no-data">当前博客不存在</div>; } return ( <div className="blog-detail-wrapper"> <h1 className="detail-title">{currentDetail.title}</h1> <div className="detail-meta"> <span>作者:{currentDetail.author}</span> <span>发布时间:{currentDetail.publishDate}</span> </div> <div className="detail-tags"> {currentDetail.tags.map((tag) => ( <span className="tag-item" key={tag}>{tag}</span> ))} </div> <div className="detail-content" dangerouslySetInnerHTML={{ __html: currentDetail.content }} /> </div> ); }
4.3 博客列表页
直接拉取列表数据渲染卡片即可:
// pages/BlogList.tsx import BlogCard1 from "../components/BlogCard1"; import { blogListData } from "../blog-database"; export default function BlogList() { return ( <div className="blog-list-page"> <h2>全部博客</h2> <div className="card-list"> {blogListData.map((item) => ( <BlogCard1 key={item.id} item={item} /> ))} </div> </div> ); }
整个方案不需要为单个博客单独创建页面或者配置路由,只要保证
blog-database.ts里的detailUrl和blog-detail-database.ts里的映射key完全一致,即可正常完成跳转、数据匹配的全流程,完美复用单个BlogDetail组件。
内容的提问来源于stack exchange,提问作者Yavuz
相关产品推荐
相关产品推荐

