注册

耗时三个月,我高仿了一个起点小说阅读器

前言


起因是最近看小说的APP广告越来越多,但不少书源内容也时常出现问题。正好摆烂太久让我很有负罪感,就想着趁着这个契机学点新的东西。公司里用的都是vue技术栈,所以我想着用vue3做个小项目,顺便熟悉一下vue3的语法。从八月开始,断断续续搞了点Demo,直到年底稍微有点空闲,才开始着手把整个项目完善起来。


项目地址


github



gitee



支持平台


平台是否支持
H5
Android
IOS
小程序需要修改renderjs

项目介绍


eReader 是一款基于 uni-app 开发的小说阅读器,功能完善,使用便捷,支持跨平台部署。移动端完全由前端实现,无需后端支持,打包后即为一个独立的APP,极大降低了部署和维护成本。H5端由于跨域问题需要启用一个简单的后端服务器,但移动端打包后完全开箱即用。


技术架构与部署



  • uni-app 的跨平台特性使得该项目在移动端和H5端之间无缝切换,移动端是纯前端实现,不依赖额外的服务器。
  • H5端需要启用后端服务器来解决跨域问题,但移动端完全是前端应用,避免了额外的服务器负担,极大简化了部署和维护流程。
  • 使用技术栈如下

    1. Vue3 + TypeScript:项目基于Vue3和TypeScript实现。
    2. Node + Express:H5端使用Node + Express搭建了一个简单的后台,负责爬取数据。
    3. uni.request:在APP端通过uni.request获取数据,不用启用后端应用。
    4. Cheerio:用Cheerio来解析HTML,提取书籍信息。
    5. uni.setStorage:数据缓存使用了uni.setStorage存储。
    6. 阅读引擎:主要是用 canvas.measureText 来计算文本宽度,通过JS计算宽高分页,支持两端对齐、标点避头等排版优化。
    7. 分页:分页计算用了uni-app的 renderjs 操作Canvas, uni.createCanvasContext 在APP端性能表现不佳,应尽量避免使用。
    8. 海报分享:海报分享功能使用了 limeui-painter



平台功能



  • 丰富的书源:内置多个书源,满足大多数阅读需求,并支持灵活切换。
  • 全面的功能:包括书架管理、小说搜索、阅读器设置(夜间模式、字体、背景主题、翻页方式)、章节缓存等,功能齐全。
  • 个性化体验:支持书签、目录跳转、缓存、夜间模式等用户自定义设置。
  • 逻辑闭环:书源管理、阅读设置、书签等功能平滑切换,确保使用流畅、体验一致。
  • 详细功能列表

    1. 书架:可以加入/移除书架、置顶小说、分享(APP端)、查看详情、搜索、小说排序和浏览历史等功能。
    2. 分组:可以管理小说分组,支持新增、删除、修改、置顶等操作。
    3. 精选推荐:集成了 夸克热搜 的书单推荐,帮助大家发现热门书籍。
    4. 我的:包括书源管理、浏览历史、夜间模式、关于、意见反馈、缓存清除和分享等设置。
    5. 小说搜索:内置了 12 个书源,基本能满足大部分人的阅读需求。
    6. 书籍详情:展示书籍信息、简介、目录等,支持分享功能。
    7. 阅读器:支持添加/移除书架、添加/删除书签、查看目录、白天/夜间模式切换、翻页方式、字号和背景主题切换等多项个性化设置。此外,还支持其余书源切换章节缓存(包括缓存全部、缓存后20章和缓存当前章节后的所有章节)。
    8. 目录:支持目录查看、缓存状态、书签、章节跳转、快速跳转(比如去当前章节、去底部)等功能。



项目结构


|-- undefined
|-- .prettierignore
|-- .prettierrc.js
|-- index.html
|-- package.json
|-- tsconfig.json
|-- vite.config.ts
|-- src
|-- App.vue
|-- env.d.ts
|-- main.ts
|-- manifest.json
|-- pages.json
|-- type.d.ts
|-- uni.scss
|-- api #请求接口
| |-- common.ts
|-- components
| |-- BookTip.vue #阅读页第一次打开提示
| |-- Expand.vue #书籍详情简介收起与展开
| |-- share.vue #分享组件
| |-- TabBar.vue #重写tabbar,没使用uni自带tabbar
| |-- global #全局组件
| | |-- g-confirm.vue #确认和输入弹窗
| | |-- g-icon-fonts.vue #图标
| | |-- g-page.vue #每个页面根元素,主要是做主题切换,设置全局css样式(uniapp的APP.vue没有根元素)
| | |-- g-popup.vue #底部和中间弹窗封装
| | |-- g-statusbar.vue #顶部statusbar占位组件,h5端高度为0,app端有默认高度
| |-- painter #海报绘制组件
| |-- popover #书架排序气泡窗
|-- directives #vLongPress指令封装
| |-- index.ts
|-- pages
| |-- blank #我的-跳转页面
| | |-- about.vue #关于我们
| | |-- agreement.vue #用户协议
| | |-- feedback.vue #意见反馈
| | |-- history.vue #浏览历史
| | |-- origin.vue #书源管理
| | |-- policy.vue #隐私政策
| |-- bookDetail #书籍详情页
| |-- catalogs #目录页
| |-- groupDetail #分组详情页
| |-- reader #阅读器
| | |-- index.vue
| | |-- index_v1.vue #第一版,使用columns布局分页
| | |-- index_v2.vue #第二版,使用canvas.measureText计算宽度,js计算宽高进行分页(算法不完善,可以看看思路)
| | |-- readerLayout.ts #第三版,感谢 [@前端一锅煮] 大佬的分享
| | |-- components
| | |-- Origin.vue #换源组件
| | |-- Renderjs.vue #使用uniapp的rendejs获取 document 文档对象
| | |-- Renderjs_v2.vue #第二版renderjs
| |-- search #搜索页
| |-- tabBar #自定义tabbar
| |-- book.vue #精选
| |-- home.vue #书架
| |-- personal.vue #我的
| |-- components
| |-- addGr0up.vue #书架、分组详情里[移至分组]功能
| |-- bookDetail.vue #书架、分组详情里长按展示详情功能
| |-- groupItem.vue #分组项
|-- parser #app端数据解析
| |-- catalog.ts #目录解析
| |-- content.ts #章节内容解析
| |-- index.ts
| |-- search.ts #搜索内容解析
| |-- source.ts #内置书源
| |-- top.ts #精选内容解析
|-- static
|-- store #store
| |-- AppOption.ts #app的系统信息
| |-- index.ts #一些缓存相关数据处理:书架、历史、缓存章节、搜索历史等
|-- styles
|-- types
|-- utils
|-- Config.ts
|-- Control.ts
|-- index.ts
|-- request.ts #请求处理和响应拦截
|-- RequestHeader.ts #最初是想伪造请求头的,但是uni的app端ua固定了

后续功能优化



  • 错误处理:当前未处理极端情况下的错误请求,导致产品在特定条件下可能不够健壮,后续会加强异常处理。
  • 网络字体支持:项目打包后APK约15MB,内置字体包增大了文件体积,后续会考虑支持网络字体加载以实现更丰富的阅读体验。
  • 书源导入与更新:第三方书源存在不稳定性,网站变动可能导致解析错误。后续会考虑支持书源离线导入和在线更新,有助于解决此问题。
  • 听书功能:作为干眼症患者,听书功能对我来说还是非常重要的,未来计划加入该功能。
  • 去除广告:第三方书源可能包含广告和无关链接,影响阅读体验。后续考虑支持长按选择内容去除,并应用到所有章节,将极大提升阅读质量。

项目展示


h5表现



  • 书架
    PixPin_2025-01-15_11-11-06.gif
  • 精选

PixPin_2025-01-15_11-33-27.gif



  • 我的
    PixPin_2025-01-15_11-23-31.gif
  • 搜索

PixPin_2025-01-15_11-35-22.gif



  • 详情

PixPin_2025-01-15_13-47-58.gif



  • 阅读器

PixPin_2025-01-15_13-51-20.gif


app端表现(IOS)



Android端未完整测试,可能存在部分兼容问题




  • 书架(亮)
    书架.jpg
  • 搜索(亮)
    081215e1ebc858e4a3e2bb6b25e7591.jpg
  • 书源管理(亮)
    97a215463434014bfca7a9e306758bb.jpg
  • 我的(亮)
    c24b6f22642b73a89fb29c61c486eda.jpg
  • 浏览历史(亮)

5378049e7f666f069a3c7893964859f.jpg



  • 分组(暗)

647cdc2d9ef238c763c0481ac3f4dd6.jpg



  • 分组详情(暗)
    605e704b77169fcfd8f6d7c75b06974.jpg
  • 我的(暗)
    0d43113e996a69f52d58813504784b5.jpg
  • 意见反馈(暗)
    ea5984628d3013dab64992e49b72e0c.jpg
  • 详情(暗)
    8c2feac4fb0a99b3be6ed359c91cdad.jpg
  • 分享

325a55ea810dde156bf03c8e9acfd1f.jpg



  • 阅读器

ios.gif


总结



  • 最初只是为了学习新技术栈,项目框架、组件设计没考虑太多。但随着功能的增加,组件复用和方法抽象的需求变得明显,过程中也渐渐感觉到有些力不从心。
  • 尽管仍有一些缺漏,但是整体来看来这个项目已经勉强算得上是一个完整的、功能闭环的产品。作为一个人独立完成,自己也算是比较满意了。
  • 开发过程中遇到了不少挑战,比如阅读器排版引擎就经历了三次重构,才最终达到了理想效果。那段时间搞得头都要秃了(本来所剩无几的发量越加稀少)。 后续会写写教程,记录下开发过程中遇到的坑。

相关


水了几篇文章,回家过年咯(逃~)



参考


感谢下面两位大佬的文章



作者:何日
来源:juejin.cn/post/7460023342592901183

0 个评论

要回复文章请先登录注册