10. 图书阅读器(technical-architecture)
1. 架构设计
本应用采用 React 前端技术栈,核心依赖 epubjs 或类似阅读引擎库来解析和渲染电子书。数据存储采用 LocalStorage 或 IndexedDB 实现离线持久化。
2. 技术描述
- 前端框架: React@18 + TypeScript + Vite
- 样式方案: TailwindCSS@3
- 路由管理: React Router DOM@6
- 阅读引擎:
epubjs或react-reader(用于解析渲染 .epub 格式电子书) - 状态管理: Zustand 或 React Context API (管理阅读设置、书架状态)
- 数据持久化: LocalStorage (存储设置、进度), IndexedDB (存储图书文件内容 - 可选)
- 图标库: React Icons (Feather / Ionicons)
- UI组件库: Headless UI 或 自定义组件 (保持轻量)
3. 路由定义
| 路由 | 路径 | 用途 |
|---|---|---|
| 书架首页 | / |
展示书架图书列表 |
| 图书分类 | /categories |
图书分类浏览 |
| 图书详情 | /book/:id |
图书详细信息 |
| 阅读页面 | /read/:id |
核心阅读器界面 |
| 搜索页面 | /search |
搜索图书 |
| 我的页面 | /profile |
用户统计、设置 |
4. 数据模型
4.1 LocalStorage / IndexedDB 存储结构
Key: reader_app_settings
{
"theme": "light", // 'light' | 'dark' | 'sepia'
"fontSize": 18,
"fontFamily": "serif",
"lineHeight": 1.5,
"brightness": 100
}
Key: reader_app_books (图书元数据)
[
{
"id": "book-uuid-001",
"title": "The Great Gatsby",
"author": "F. Scott Fitzgerald",
"coverUrl": "/assets/covers/gatsby.jpg",
"fileUrl": "/assets/books/gatsby.epub",
"format": "epub",
"category": "Fiction",
"addedAt": 1678888888,
"lastReadAt": 1679999999,
"progress": {
"cfi": "epubcfi(/6/4[chap01ref]!/4/2/1:0)", // epubjs 定位格式
"percentage": 0.15,
"chapterName": "Chapter 1"
}
}
]
Key: reader_app_bookmarks
[
{
"id": "mark-uuid-001",
"bookId": "book-uuid-001",
"cfi": "epubcfi(/6/4[chap01ref]!/4/2/1:0)",
"text": "In my younger and more vulnerable years...", // 选中文字预览
"createdAt": 1679999999
}
]
4.2 TypeScript 类型定义
// 图书元数据
interface Book {
id: string;
title: string;
author: string;
coverUrl: string;
fileUrl: string; // 本地路径或远程URL
format: 'epub' | 'pdf' | 'txt';
category: string;
description?: string;
addedAt: number;
lastReadAt?: number;
progress?: ReadingProgress;
}
// 阅读进度
interface ReadingProgress {
cfi: string; // EPUB CFI 用于精确定位
percentage: number; // 0-1
chapterName?: string;
}
// 书签
interface Bookmark {
id: string;
bookId: string;
cfi: string;
text: string;
createdAt: number;
}
// 阅读设置
interface ReaderSettings {
theme: 'light' | 'dark' | 'sepia';
fontSize: number;
fontFamily: string;
lineHeight: number;
brightness: number; // 模拟亮度,实际可能通过遮罩实现
}
5. 前端架构设计
5.1 组件结构
src/
├── components/
│ ├── common/ # 通用组件 (Button, NavBar, TabBar)
│ ├── book/ # 图书相关组件
│ │ ├── BookCard.tsx
│ │ ├── BookList.tsx
│ │ └── BookCover.tsx
│ ├── reader/ # 阅读器核心组件
│ │ ├── ReaderEngine.tsx # 封装 epubjs/react-reader
│ │ ├── ReaderMenu.tsx # 顶部/底部菜单
│ │ ├── ReaderSettings.tsx # 设置面板
│ │ └── TocDrawer.tsx # 目录侧边栏
│ └── search/
│ └── SearchBar.tsx
├── pages/
│ ├── Bookshelf.tsx
│ ├── Categories.tsx
│ ├── BookDetail.tsx
│ ├── ReadPage.tsx
│ ├── Search.tsx
│ └── Profile.tsx
├── contexts/
│ ├── ReaderContext.tsx # 管理当前阅读状态
│ └── SettingsContext.tsx # 全局主题设置
├── hooks/
│ ├── useBook.ts
│ └── useReaderSettings.ts
└── utils/
├── epubHelper.ts # epubjs 辅助函数
└── storage.ts
5.2 关键逻辑
-
图书解析与渲染:
- 使用
epubjs加载.epub文件。 ReaderEngine组件负责初始化ePub对象,挂载到 DOM 节点。- 监听
relocated事件以更新当前页码和进度。
- 使用
-
阅读状态同步:
- 每次翻页时,获取当前
cfi(Canonical Fragment Identifier)。 - 将
cfi和计算出的百分比保存到 LocalStorage (reader_app_books中的progress字段)。 - 下次打开书时,读取
progress.cfi并调用rendition.display(cfi)恢复位置。
- 每次翻页时,获取当前
-
夜间模式与主题:
epubjs支持themes.register和themes.select。- 预定义 CSS 样式(如背景色、文字颜色)注册为不同主题。
- 用户切换主题时,调用
rendition.themes.select('dark')。
-
书签功能:
- 用户点击添加书签时,获取当前范围的
cfi。 - 可选:获取当前页的文本摘要作为书签预览。
- 保存至
reader_app_bookmarks。
- 用户点击添加书签时,获取当前范围的
-
离线支持:
- 简单的离线支持:将 epub 文件转换为 ArrayBuffer 或 Blob 存储在 IndexedDB。
- 每次读取时从 IndexedDB 取出 Blob URL 传给阅读引擎。
20大项目拆解:从PRD到架构 文章被收录于专栏
想独立做出一个完整的项目却不知从何下手?本专栏是你的终极路线图。我们由浅入深,通过20个经典项目案例,手把手带你走过产品构思、需求撰写、功能设计、技术选型、架构搭建的全过程。从“音乐播放器”到“企业后台”,你将逐步建立对软件系统的完整认知,完成从理论到实践、从单一技能到复合能力的飞跃。