需求评审是在周三下午。
会议不长,只有三十分钟,主题也只有一个——
阅读体验优化(v1.1)****
林晨一开始并没太在意这个标题。
“v1.1”通常意味着什么,他太熟了:
不是推翻重来,而是在现有结构上“顺手改一下”。
问题往往就出在“顺手”。
“我们收到了第一轮内部反馈。”
苏雨翻开文档,语气很平稳。
“大家普遍觉得现在的阅读体验不错,但有一个点——”
她停顿了一下,看向林晨。
“切换章节时,有一点‘断’。”
林晨没有接话。
他知道这句话的后半段一定是关键。
“所以我在想,”苏雨继续说,“能不能把章节做成连续滚动?就像微信读书那样。”
会议室里安静了一瞬。
不是因为这个需求多离谱,
而是因为它听起来太合理了。
张明先开口:“这个对用户来说挺友好的吧?”
UI 设计师王雪也点头:“从视觉上看,会更沉浸。”
所有目光,最后落在林晨身上。
林晨没有立刻反驳。
他低头翻了一页笔记,像是在确认什么。
然后他说:
“这不是样式问题。”
语气不重,却让人下意识坐直了些。
“现在的实现,”
林晨解释,“是章节级渲染。”
他在白板上画了几个方框。
[ Chapter 1 ] -> render
[ Chapter 2 ] -> render
[ Chapter 3 ] -> render
“切换章节,本质是卸载一个 DOM 树,挂载下一个。”
“连续滚动意味着什么?”
他又画了一条长线。
[ Chapter 1 ][ Chapter 2 ][ Chapter 3 ] ...
“意味着我们要同时管理多个章节的 DOM 生命周期。”
苏雨皱了下眉:“但这不就是多渲染一点内容吗?”
林晨摇头。
“不是‘一点’。”
他把笔记本转过来,调出一段简单的计算。
// 平均每章 20 段
// 每段 ≈ 2~3 个 DOM 节点
// 300 章 ≈ 12000 ~ 18000 个节点
“这是理想情况。”
他说,“还没算图片、注释、高亮。”
会议室里安静下来。
不是所有人都完全理解这个数字的意义,
但都能感觉到——不轻松。
“那微信读书怎么做的?”
有人问。
林晨没有露出“早就料到”的表情,只是平静回答:
“它一定不是一次性渲染全部。”
“要么是虚拟滚动,要么是分页加载 + DOM 回收。”
“而这两种方案,都不是‘改一点点’。”
苏雨沉默了几秒。
“如果我们只做前后各一章呢?”
她试探着问,“比如,当前章节 + 上一章 + 下一章。”
林晨抬头,看了她一眼。
这一眼不是对立,而是认真。
“那就意味着状态模型要改。”
他重新在白板上写:
// 现在
currentChapterIndex: number
// 变更后
visibleChapters: number[]
activeAnchor: {
chapterIndex: number
offset: number
}
“你看,”他说,“这不只是多渲染。”
“滚动位置不再只属于一个章节,
进度保存逻辑、书签逻辑、跳转逻辑,都会被牵连。”
“这是状态复杂度的跃迁。”
张明有些犹豫:“但用户体验也很重要……”
“我不是反对体验。”
林晨接得很快。
“我是反对在不重构的前提下追求体验。”
这句话落下时,空气明显紧了一下。
不是冲突爆发,
而是立场第一次被清晰地摆上桌面。
苏雨终于开口。
“那你的建议是?”
林晨没有犹豫。
“如果要做连续滚动,”
他说,“我们要把它当成 v2 的核心能力。”
“现在这个阶段,可以优化切换动画、预加载下一章,但不合并 DOM 生命周期。”
“否则,后面每加一个功能,都会踩在不稳定结构上。”
会议结束时,没有结论。
不是失败,而是被按下了暂停键。
大家陆续离开会议室。
林晨收拾电脑时,苏雨还坐着没动。
“你是不是觉得我在‘卡需求’?”
她忽然问。
林晨停下动作。
“我觉得你在为用户争取体验。”
他说,“而我在为系统争取寿命。”
苏雨苦笑了一下。
“听起来,我们站在两边。”
“不。”
林晨摇头,“我们站在同一条线的不同时间点。”
晚上,林晨回到工位,没有立刻写代码。
他新建了一个分支。
feature/virtual-scroll-prototype
不是要交付,
而是给未来留一条路。
// 预研:虚拟章节渲染
// 原则:
// 1. 只保留可视区 DOM
// 2. 滚动不触发全量 diff
他知道,这段代码也许一周内都用不上。
但他更清楚——
真正的风险,从来不是需求变更本身,
而是在错误的结构上继续加东西。
深夜,苏雨发来一条消息。
我回去想了很久。
连续滚动,我们先放到 v2。
v1 只做体验优化。
林晨盯着屏幕,过了几秒才回。
谢谢你愿意听技术的“不好听部分”。
这一次,苏雨回得很快。
谢谢你不是一句“做不了”就结束。
这一晚,他们都没再说话。
但两个人心里都很清楚:
这不是最后一次冲突,
甚至不是最激烈的一次。
只是第一次,
他们选择了不互相消耗。