毕设答辩那天,端毕我站在讲台上,业设PPT 的计论动画效果突然卡住了。台下评委老师皱了皱眉,端毕我手心冒汗,业设但代码里早就写好了降级方案——那个按钮在无动画状态下依然能正常点击。计论这是端毕我整个毕业设计里最得意的一笔,比任何花哨的业设交互都让我踏实。
我的计论题目是《基于 Vue 的校园二手交易平台前端设计与实现》。选题没什么新颖的端毕,但做起来才知道,业设前端这活儿,计论看着是端毕画界面,实际上是业设在跟浏览器斗智斗勇。三个月里,计论我删掉的代码比留下的多。最开始的版本用 jQuery 写的,功能倒是能跑,可每次新增一个页面,全局变量就像乱掉的毛线团,扯一根带出一片。后来咬着牙推倒重来,换成 Vue 全家桶,状态管理用 Vuex,路由用 Vue Router。那感觉就像从骑三轮车换成了开轿车——不是快了,是方向盘终于在自己手里了。
真正让我开窍的是性能优化。我做了个商品列表页,图片懒加载、虚拟滚动、按需引入组件库,能做的都做了,可 Lighthouse 评分还是卡在 78 分。排查了一整天,最后发现是某个第三方 UI 库的样式文件被整包打进来了。用 webpack-bundle-analyzer 一看,一个没用到的日期选择器组件居然占了 200KB。删掉那行 import 之后,评分直接跳到 92。我盯着屏幕愣了几秒,突然明白了什么叫“前端无小事”——每一个字节都是自己挣来的。
写 CSS 的时候我犯了所有新手都会犯的错——用 px 写死了所有尺寸。直到导师让我在手机上打开测试页面,那个原本整齐的卡片布局像被揉皱的纸一样挤在一起。后来我老老实实改成 rem + flex 布局,又用媒体查询处理了几个临界点。说实话,响应式设计没什么高深的,就是得一遍遍把浏览器窗口拖来拖去,拖到你自己都想吐为止。但当你看到同一个页面在 iPhone SE 和 4K 显示器上都能舒服地展示时,那种满足感是实实在在的。
最让我纠结的是登录注册模块的交互细节。密码框的“显示/隐藏”切换按钮,我做了四个版本——第一个版本按钮太小,手指点不准;第二个版本图标含义不明,有人以为是刷新;第三个版本切换时密码框会跳动,因为输入框的内边距变了。最后定稿的版本在按钮下方加了一行小字提示,而且用 CSS 动画让图标旋转 180 度过渡。这个细节可能在别人眼里微不足道,但我知道,用户不会为这 0.3 秒的动画鼓掌,却会因为那 0.1 秒的跳动而烦躁。
论文里我写了很多技术方案对比,但真正想记录的是那些调试到凌晨两点的时刻。有一次 flex 布局死活不换行,我怀疑是浏览器 bug,最后发现是父容器忘了设 min-width:0。还有一次 Vue 的 computed 属性不更新,折腾了半小时,结果是 data 里某个字段名拼错了。这些错误都很蠢,但正是这些蠢错误,让我从“会写页面”变成了“会思考页面为什么会出问题”。答辩时老师问我:“你觉得前端和后端的本质区别是什么?”我说:“后端追求的是数据不出错,前端追求的是用户不出错。”老师们笑了,我也笑了——因为那是被无数个崩溃的夜晚逼出来的答案。
现在回看这个毕设,代码质量其实一般,架构也不算优雅。但它是我第一个真正完整的产品——从需求分析到视觉稿,从接口联调到真机测试,每个环节都亲手碰过。我甚至给商品图片加了 WebP 格式的降级处理,因为有个用户反馈说他的旧手机显示不了图片。那些在控制台里刷过的报错、在源码里翻过的文档、在 Stack Overflow 上点过的赞,最后都变成了论文里一句句平淡的“经过测试,系统运行稳定”。但只有我知道,那句“稳定”背后,是多少次不稳定的尝试。