前言
为什么会有这本书?
2013年,我写下了人生中第一行代码。和很多人一样,我学编程的方式是看视频教程、跟着敲代码、复制粘贴。这样做确实能做出东西——一个ToDo List应用、一个天气预报页面、一个博客系统。教程说做什么,我就做什么。教程说怎么改,我就怎么改。
但有一个问题始终困扰着我:离开教程之后,我什么都不会。
我不知道为什么要用这个库而不是那个库。我不知道为什么文件要这样组织而不是那样组织。我不知道当代码报错时,除了重新看一遍教程、或者在CSDN上复制一段代码碰运气之外,还能做什么。我不知道怎么把一个想法——一个完完全全属于自己的想法——从零变成现实。
这种感觉,就像一个学做菜的人,把菜谱背得滚瓜烂熟,但一旦给他一堆陌生的食材,他就站在厨房里手足无措。他缺的不是菜谱,是对食材本身的理解,是刀工火候的直觉,是“这个菜为什么这样做”的第一性原理。
这本书,就是为那些不再满足于“跟着做”、而是想知道“为什么这样做”的人写的。
这本书在讲什么?
本书围绕一个真实完整的开源项目——THE118™ · 3D 交互式化学元素周期表——展开。项目源码托管在 GitHub,基于 MIT 协议开源。你可以在线体验最终效果:the118.pro。
THE118不是一个“为了教学而编造的玩具项目”。它是一个有真实应用价值的Web应用:展示118个化学元素,支持五种3D布局(表格、球体、螺旋、网格、随机)之间的流畅切换,支持鼠标拖拽旋转和惯性动画,支持元素聚焦和详情查看,支持明暗主题切换。它不使用Three.js或任何第三方3D图形库——所有的3D渲染,完全依靠自定义的4x4数学矩阵运算和CSS的 matrix3d 函数来实现。
在这本书里,我们将从零开始,一步一步把这个项目完整地搭建出来。你会亲手写一个矩阵运算引擎,亲眼看到一个元素周期表从无到有地在你面前诞生。但这本书不只是教你写代码——它会告诉你每一步“为什么这样做”,以及“还有哪些做法,我们为什么选了这一种”。
这是一本“授人以渔”的书。学完之后,你不只会做这个项目,你还会获得一种通用的能力:面对一个未知的技术难题,知道从哪里开始思考、如何拆解问题、怎样做出决策。
这本书适合谁?
如果你符合以下任何一种情况,这本书应该会对你很有帮助:
你是一个前端初学者,已经学过HTML、CSS和JavaScript的基础语法,能写出简单的页面,但不知道怎么把“一堆零散的代码”组织成一个“完整的项目”。你不知道什么是工程化,不知道Git除了 commit 和 push 还能干什么,不知道为什么团队开发需要那么多配置文件。
你是一个自学了一段时间前端的开发者,跟着教程做过几个项目,但总觉得“离开了教程就什么都不会”。你隐约感觉到,自己和“专业前端工程师”之间隔着一层看不见的墙,你想打破它。
你对计算机图形学或者线性代数在实际项目中的应用感到好奇,想看看矩阵到底是怎么让元素在屏幕上转起来的,而不是只在教科书上算行列式。
你想学习“如何设计软件架构”——不只是怎么写一个组件,而是怎么把几十个组件、几十个状态、几十个数据服务组织成一个清晰的、可维护的整体。
你正在准备自己的第一个“拿得出手的作品”——不是教学示例的ToDo List,不是仿写的小米商城,而是一个真正属于你自己的、从零设计并实现的项目,可以自豪地放在简历上。
这本书不适合谁?
坦诚地说,这本书并不适合所有人。如果你属于以下情况,这本书可能会让你感到挫败,我建议你先打好基础再回来看。
你对HTML、CSS、JavaScript完全零基础。 本书不会从“什么是变量”、“什么是DOM”开始讲。如果你还不会写基本的前端三件套代码,请先去学习基础教程,做完几个简单的静态页面,再来读这本书。这不是因为本书的门槛有多高,而是因为我不想浪费你的时间——对着看不懂的术语死磕,不如先去补齐基础。
你想在三天内速成一个项目,应付面试或作业。 这本书不教“最快的做法”,它教“最透彻的做法”。我们会在第6章和第7章停下来,花整整两章的篇幅去写数学工具库——不是因为不会调CSS的 rotateX,而是因为我们要理解底层。如果你追求速成,这本书会让你不耐烦。
你对“为什么要这样做”完全不感兴趣。 如果你的核心诉求是“给我一段能跑的代码就行”,那这本书可能不是最好的选择。这本书最大的篇幅不是用在展示“最终代码”上,而是用在解释我们为什么走到了这里上。每一个技术选型、每一处架构设计,都会展开讨论它的背景、优劣和取舍。
你只想学React,不想碰数学。 本书涉及大量的线性代数——4x4矩阵运算、齐次坐标、变换组合、三角函数。如果你对这些内容完全没有兴趣,只想学React的Hook和组件通信,那我推荐你去看React官方文档或者专门的React教程。本书的数学部分不是点缀,而是核心。
这本书的技术深度
本书的技术覆盖面比较广,但并不追求每个方向的“高级”深度。我们的目标是打通一个完整项目从头到尾的完整链路,让你看到每一个环节的真实样貌。具体来说:
工程化基础:Git、ESLint、Commitlint、Husky、Vite配置、路径别名、环境变量——这些是专业前端开发者的日常工具,本书会在项目初始阶段一次性配好,并解释每个工具的意义。
TypeScript:本书所有代码都用TypeScript编写,不会用 any 来糊弄。但TypeScript本身不是本书的主角——我们不会深入类型体操或高级泛型,我们只用TypeScript做好类型安全这件最基本的事。
线性代数与矩阵运算:这是本书最有特色的部分。我们会从零实现一个4x4矩阵运算库,包括平移、旋转、缩放矩阵的构造,展开循环的矩阵乘法优化,以及复合变换的组合逻辑。不需要你有线性代数的基础——我会用最直观的方式解释每个公式的含义。
React与状态管理:本书使用React 19 + Context + Hooks来构建UI和状态管理。我们会设计四个独立的Context来管理不同的状态域,讨论Provider的嵌套顺序、惰性初始化和性能优化策略。
架构设计:这是本书的另一个核心。我们会先搭建一个传统的分层架构,然后在书的第五部分,主动审视它的缺陷,引入FSD(Feature-Sliced Design)进行重构。你会看到:架构不是一开始就设计完美的,它是演化出来的。
测试与部署:本书会为数学工具和布局算法编写单元测试,并把测试挂到Git Hooks上。最后,我们会用GitHub Pages把项目部署上线,绑定自定义域名。
如何使用本书?
这本书不是一本“地铁读物”——你不会在通勤路上翻两页就能学到东西。它需要你坐在电脑前,打开编辑器,跟着每一章的步骤亲手写代码。
每一章都依赖前面章节的成果,所以建议你按顺序阅读,不要跳章。如果你在某一章卡住了,可以先去GitHub仓库查看对应阶段的源码,对照着找问题。
每一章末尾都有一个“扩展思考”或者“调试彩蛋”——这是留给你的练习题。它们不是选做的,而是帮助你巩固理解的必经之路。
书中的代码并不是“最终版本”。在第16章到第19章的重构部分,我们会主动修改甚至推翻前面的代码。这可能会让你觉得“之前的努力白费了”,但请相信——这不是浪费,这是演化。真实世界的软件就是这样,没有一蹴而就的完美设计。
善用Git。 在每一章结束后,commit你的代码。这样,当你读到重构章节、需要大幅改动代码时,你随时可以回退到之前的版本,或者查看“重构前”和“重构后”的差异。Git不只是存档工具,它是你的学习笔记。
致谢
这本书的诞生,离不开很多人的帮助。
感谢凯尔·辛普森的《你不知道的JavaScript》——这套书教会我,技术写作可以像侦探小说一样引人入胜。你会在本书的叙述风格中,看到它深深的影子。感谢查尔斯·佩措尔德的《编码》——它证明了一件事:再复杂的技术,只要从第一性原理出发,都能被清晰地解释。本书的“不教怎么用、教为什么这样设计”的理念,就来源于此。
感谢THE118项目的所有早期体验者和反馈者。你们在项目还处于粗糙原型阶段时就开始关注它,并提出了宝贵的改进建议。
感谢你——本书的读者。你选择了一条更难的路:不满足于“能跑就行”,而是追问“为什么能跑”。在这个追求速成的时代,这是一种稀缺而珍贵的品质。
最后感谢我最敬爱的母亲——在我人生最迷茫的的时期,是她在一直鼓励着,支持着我!我才得以对本书进行撰写工作。
获取更多帮助与反馈
本书的配套源码在 GitHub 上开源,你可以在线体验最终效果:the118.pro。如果你在阅读过程中发现了错误——无论是技术错误、拼写错误还是逻辑错误——欢迎提交Issue或Pull Request。
如果你在使用本书或THE118项目的过程中遇到任何问题,或者有任何建议、合作意向,欢迎通过以下方式与我联系:
- 电子邮箱:emmakyitt@gmail.com
- GitHub:github.com/emmakyitt
我无法保证立刻回复每封邮件,但我一定会认真阅读每一封来信。
由于作者水平和学识有限,书中难免存在疏漏、错误或表述不够准确之处。本书所涉及的技术栈——React、TypeScript、Vite、FSD架构等——均处于快速迭代之中,书中内容虽力求与当前最新版本保持一致,但技术的演进速度往往快于书籍的出版周期。因此,部分细节在您阅读时可能已发生变化,敬请留意相关技术的官方文档以获取最新信息。
本书的写作过程,也是作者自身学习和反思的过程。每一次重读已经写下的章节,都能发现可以改进的地方。这正是软件工程的魅力所在:没有完美的代码,也没有完美的书籍,只有不断迭代、不断完善的追求。
敬请广大读者不吝批评指正,并提出宝贵意见。你们的反馈,将是本书持续改进的最大动力。
好了,让我们开始吧。翻开下一页,第1章见。
emmakyitt
2026年5月
第一章:嘿,抬头看!欢迎来到3D元素世界
1.1 一个可能你也曾有过的想法
你可能在化学课上,对着化学课本最后一页的那张密密麻麻的元素周期表发过呆;也可能在网上看到过一些很酷炫的、可以旋转拖拽的3D元素周期表网站。那些红绿蓝紫的小卡片,在屏幕上转来转去,看起来充满了“科技感”。
我也一样。
有一天我盯着屏幕上那个漂亮的3D化学元素周期表,脑子里突然冒出了一个想法,不是“哇,好厉害”,而是:
“如果让我自己从零开始写一个,不依赖任何所谓的‘3D图形库’,我能做到吗?”
这个想法一直在我的脑海中挥之不去。最终,我决定试一试。而这个项目,就是你即将要亲手构建的 THE118™ · 3D 交互式化学元素周期表。
它不仅仅是一个Web 3D 项目,更是一个完美的学习沙盒:它有你足够熟悉的业务逻辑(毕竟我们都背过“氢氦锂铍硼”),但它的实现方式,却足以挑战和重塑你对Web前端能力的认知。
通过这本书,你将会:
- 亲手搭建一个完整的前端工程化项目,而不是用工程模版一键生成。
- 理解3D图形在浏览器中绘制的数学本质,而不是只会调用库的API。
- 掌握如何管理一个复杂应用的状态,让代码不再是一团乱麻。
- 学会用“架构师”的视角去审视代码,并亲手重构它,让它变得更加强壮。
- 能够发布你的项目代码并将它部署到互联网上去,让全世界的人都能看到它。
- 明确你的习路径与职业成长,对它们有清晰的认知和规划能力。
但最重要的是,我希望带给你一种信念:那些看起来无比复杂、透着神秘光芒的软件,在拆开它们外壳之后,都是由最基础、最朴实的技术构成的。你完全可以理解它们,也可以创造它们。
1.2 我们到底要做一个什么东西?
在开始写第一行代码前,我们得先搞清楚我们的目标。用软件工程的话来说,这叫“需求”。
核心功能(MVP,最小可行产品):
- 在浏览器中展示118个化学元素卡片,每个卡片至少显示原子序数和元素符号。
- 并提供5种3D布局方式:标准的表格、一个大球、一段螺旋、一个魔方似的网格、以及一个看起来完全随机的元素分布。
- 然后能流畅的切换这五种布局,同时还应该有过渡动画。
交互体验:
- 点击一个卡片,它能“飞“到屏幕中央,让你看个清楚。
- 双击一个卡片,弹出一个元素详情面板,告诉你它的名字、用途等信息。
- 拖拽整个3D场景,它能转起来。且在松手的那一刻,不是立刻停住,而是像一颗打出去的冰球——缓慢停止。
其他一些锦上添花的事:
- 项目应该支持亮色和暗色主题。
- 整个项目要严格遵守代码规范。
是不是感觉要做的还蛮多的?别怕。我们不会试图一口吃成个胖子。回顾一下我们是抱着什么心态来做这个项目的:学习。甚至我们现在可以非常自信的断定,代码在未来一定是会被我们重写的,因为随着我们能力的增长,我们会越来越看不惯自己刚开始时写的那些“幼稚”的代码。这很正常,甚至可以说是一件值得高兴的事情。
所以,放轻松,享受这个创造的过程。
1.3 为什么我们要选择一条“更难”的路?
现在,我们要做出一个贯穿全书的最重要的决定。这个决定,将会定义我们整个项目的技术灵魂。
如果你去网上搜 “Web 3D 元素周期表”,99%的项目都会用到一个叫做 Three.js 的图形库。Three.js 是一个非常伟大的库,它把复杂的 WebGL 指令包装成简单易懂的 JavaScript 对象,让你能轻松地创建图形、灯光和摄像机等。
那为什么我们不用?
你想象一下,你是想成为一个只会驾驶“自动档汽车”的司机,还是一个能在发动机出问题时,打开引擎盖就知道该拧哪个螺丝的机修师?
Three.js 就是那个“自动档汽车”。它把我们和底层那些迷人的数学原理隔离开了。我们使用它,能做出东西,但我们不知道它为什么能工作。
我们这本书的目标,就是打开那个“引擎盖”。深入到底层,去触摸那些构成了整个3D世界的、看似枯燥却威力无穷的线性代数数学矩阵。
这,就是我们选择这条“更难”的路的原因。因为我们追求的不仅仅是“做到”,更是要“知道”。我们要的,是那种“一切尽在掌握”的自由。
1.4 你的学习旅程地图
下面是我们将要一起走过的路。我会把它分成三个大阶段,就像玩游戏升级一样。
第一阶段:新手村 · 磨刀不误砍柴工 (第2章 - 第6章)
在这个阶段,我们不写一行业务代码。我们会专注于搭建一个“专业”的开发环境。这听起来可能有点无聊,但它能让我们从一开始就养成受益终身的职业习惯。
- 环境与工具: 从零配置 Git, Node.js, Vite, TypeScript。
- 代码规范: 学会用 ESLint, Commitlint, Husky 来让你的项目保持整洁。
第二阶段:打怪升级 · 从原理到实现 (第7章 - 第17章)
这是本书最核心、最有挑战,也是最有成就感的阶段。我们将从最底层的数学矩阵开始,一步步构建出我们的3D元素舞台。
- 数学引擎: 亲手写一个4x4矩阵计算工具包。
- 领域核心: 实现那五种酷炫的元素卡片布局算法。
- 前端交互: 用React把我们的数据变成看得见、拖得动的3D元素。
第三阶段:觉醒时刻 · 重构与进化 (第18章 - 第25章)
等到整个项目跑起来之后,我们不会就此止步。我们会站在一个更高的角度,审视我们之前写过的代码。
- 代码评审: 一起找出项目代码中的“坏味道”。
- 架构重构: 学习更先进的FSD架构,并动手改造我们的项目。
- 放眼未来: 总结一路走来的收获,并聊聊如何成为一名更专业的软件工程师。
好了,旅行地图已经展开。我们旅程的第一步,将不是令人兴奋的3D画面,而是每一个专业项目开始的地方:需求分析与项目规划。不要小看它,正是这一步,让我们不至于在复杂的代码海洋中迷航。
现在,让我们深吸一口气,翻到下一页。
第二章:看不见的蓝图 —— 需求分析与项目规划
2.1 一个价值百万的好习惯
想象一下,你如果要决定亲手建造一座房子。你会热血上涌,立刻冲到建材市场去买水泥和砖头吗?
当然不会。
你一定会先坐下来,然后找张白纸,画一张草图。标注哪里是客厅,哪里是卧室,门朝哪开,窗户要多大。有了这张图,你才知道该买多少砖,水管怎么铺,电线往哪走。没这张图就开工,建出来的可能不是房子,而是一堆昂贵的废墟。
软件开发和盖房子一模一样。
那张“草图”,在软件开发的世界里,就叫做需求分析和项目规划。它可能是你整个项目中最不“性感”的部分——没有代码,没有动画,没有炫酷的效果。
但请相信我,它绝对是你整个项目中最有价值的部分。
为什么?因为这个习惯能把你的思维模式从 “我能做什么” 转换成 “我应该做什么” 。它能帮你在被代码细节吞没之前,先看清楚整片森林的模样。
这是我们给自己的第一个专业训练。
2.2 第一步:把“我想要”变成“用户想要”
千万别被“需求分析”这四个字吓到。对于我们这个独立开发的项目,它其实很简单,就是回答三个问题:
- 谁会用它? —— 可能是化学爱好者、学生、或者只是想看点酷炫东西的普通人。
- 他们能用它做什么? —— 这是我们定义功能的地方。
- 我们如何衡量成功? —— 功能做到什么程度才算“完成了”?
为了更好地回答这些问题,我们引入一个工具,叫做用户想要(User wants)。它的格式简单得不像话:
作为一个 [用户角色],我希望 [做某件事],以便 [达到某个目的]。
这个句式强迫我们站在用户的角度思考问题,把我们自身带入到用户的视角中去,而不是站在开发者的角度去炫技。我们来尝试写几条:
- 作为一个对化学元素很感兴趣的人,我希望在页面上看到所有118个元素,以便对元素周期表有一个整体的认识。
- 作为一个喜欢探索的用户,我希望能够用鼠标拖拽旋转整个元素集合,以便从不同角度观察它们。
- 作为一个对画面效果有极致要求的人,我希望能够切换不同的3D布局(比如球体、螺旋),以便用更直观的方式理解元素之间的关系。
- 作为一个想要深入研究某个元素的用户,我希望点击某个元素后能查看它的详细信息(如名称、用途、原子质量),以便获取我需要的具体知识。
你看,这样一来,我们想要做的那些“功能”就不再是浮于空中的想法,而是一个个服务于具体用户、有具体目的的任务。
2.3 第二步:区分“必要”与“锦上添花”
有了”用户想要“,我们就有了一个功能清单。但一股脑全做进去,我们的项目可能永远也做不完。这时候,我们就必须要学会做一个艰难的判断:分清主次。
这里我们要再次引入第一章提到的那个工具,叫做MVP(Minimum Viable Product,最小可行产品)。
它不是指一个烂到让人没法用的半成品,它指的是:用最少的功能,来验证我们核心想法的产品。对于THE118™项目,我们的核心想法是“纯数学驱动的3D元素周期表”。那么,能让这个想法跑起来的最小功能集是什么呢?
我们可以把功能分成三类:
- P0(核心功能,必须做):没有它,项目就不成立。
- P1(重要功能,应该做):让产品更好用、更完整。
- P2(增强功能,可以做):锦上添花,未来有时间再加。
来看看我们的清单:
| 功能 | 优先级 | 理由 |
|---|---|---|
| 展示全部118个元素 | P0 | 这是周期表的基本定义 |
| 5种3D布局及切换动画 | P0 | 项目的核心亮点,“纯数学驱动3D”的体现 |
| 鼠标拖拽旋转场景 | P1 | 让3D场景真正可交互,极大提升体验 |
| 点击元素查看详情 | P1 | 从“看”到“探索”的升级,让应用更有深度 |
| 元素详情面板 | P1 | 承载详情信息的容器 |
| 亮色/暗色主题切换 | P2 | 提升视觉体验和长时间使用的舒适度 |
| 搜索特定元素 | P2 | 方便用户快速定位,但交互上与点击聚焦有重叠 |
| 移动端适配 | P2 | 让手机用户也能使用,涉及更多交互适配 |
| 多语言国际化 | P2 | 让更多国家的用户能使用 |
这个优先级列表,就是我们项目的“施工计划书”。我们会严格遵循它,先集中精力完成所有P0功能,让它成为一个能跑通的项目。然后,我们再从容地加上P1和P2,不断完善它。
一个给自己的承诺:在完成P0之前,我绝不会分心去做P2的事情。这是避免项目无限期拖延的黄金法则。
2.4 第三步:画一张“导游图”
文字描述有时不够直观。尤其是当我们在设计交互流程时,一张图胜过千言万语。
现在,我们试着画一张简单的流程图,描述用户从进入网页到查看元素详情的完整路径。这在软件工程中,也是一个标准动作。
text
[用户打开网页]
│
▼
[看到默认的3D布局 (比如表格)]
│
├─ 鼠标拖拽 ───▶ [旋转/缩放场景]
│
├─ 点击底部图标 ───▶ [切换到其他3D布局 (球体/螺旋等)]
│
└─ 点击某个元素 ───▶ [元素飞到屏幕中央,高亮显示]
│
├─ 点击空白区域 ───▶ [元素退回原位]
│
└─ 双击该元素 ───▶ [弹出详情面板]
│
└── 点击遮罩层 ───▶ [关闭面板]
这张流程图虽然简单,但它就是我们编写代码的“导游图”。当我们迷失在各种 Hooks 和组件里的时候,回到这张图,它总能提醒我们:用户接下来应该去往哪里。
2.5 最后一步:写下我们的里程碑
有了功能清单和交互流程,我们就可以制定一个粗略的版本计划。这不只是为了好看,而是为了给自己设立一个个可以庆祝的“里程碑”,让漫长的开发旅程变得有节奏、有成就感。
我们可以简单地将功能映射到之前设想的三个版本中:
| 版本 | 核心任务 | 里程碑意义 |
|---|---|---|
| v0.1.0 | 展示118个元素,实现5种3D布局及切换动画 | 核心引擎跑通:证明我们自研的数学矩阵方法是可行的 |
| v0.2.0 | 加入拖拽旋转、卡片点击选中与聚焦、详情面板 | 交互体验成型:用户终于可以用手去探索这个3D世界了 |
| v1.0.0 | 加入主题切换、搜索、移动端适配、国际化等 | 产品完整发布:这是一个可以骄傲地分享给任何人的作品 |
好了,我们已经花了一整章的时间,还没写一行代码。你是不是觉得有点手痒了?
但我希望你能记住这种“先规划,后行动”的感觉。这是一种强大的方法论。从下一章开始,我们将要做出一个更关键的、甚至可能有些颠覆常识的技术决策。
我们为什么放弃了别人都在用的 Three.js?又为什么选择了一条看似更难的路——去直接操控 CSS transform 中的 matrix3d() 函数?这背后的“为什么”,才是我们整个项目中最闪亮的部分。
准备好打开“引擎盖”了吗?