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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 05:15:03