场域手记
NEXTFIELD / FIELD NOTESI — 前端
CHAPTER 01 / WRITINGFIELD NOTE 24

组件卸载后,哪些东西还在工作

消失的是组件,不一定是它创建的工作。从动画帧、事件监听到网络请求,给每个开始安排一个结束,才能让交互界面长期保持稳定。

前端2026-10-023 分钟阅读

向下阅读

一个面板关掉之后,画面看起来已经安静了。但如果它创建的动画帧还在运行、事件还在监听、请求还在等待,消失的只是 DOM,不是这段功能占用的工作。

这类问题经常在第一次打开时不明显。反复打开、关闭,或者在几个页面之间来回切换之后,重复监听、旧请求和闲置绘制才逐渐显露。界面需要考虑的时间范围,比一次成功展示更长。

从“谁创建”开始列清单

组件可能创建动画时间轴、浏览器监听、观察器、定时器、图形上下文和网络请求。它们都可以由一个组件启动,但并不因为这个组件不再可见就自动结束。

一个简单的方法,是在实现时为每个开始写下对应的结束:添加监听之后在哪里移除,申请动画帧后如何取消,创建观察器后何时断开,发起请求后谁负责中止。先列出所有权,再决定清理放在哪个生命周期中。

只有返回一个清理函数,也不意味着工作已经完整结束。回调闭包里可能还保存旧状态,另一个作用域可能重新启动任务;依赖变化也可能让同一段初始化再次发生。创建与释放需要针对实际对象,而不是凭借“已经写了 cleanup”获得安心。

隐藏与卸载不同

有些面板关闭后会卸载内容,适合直接释放内部动画和图形资源。有些播放器必须跨页面保留,不能因为某个页面消失就销毁真正发声的节点。这两种需求需要不同的所有者。

全站会话可以留在长期存在的组件中,面板只负责显示。这样,关闭助手不会抹掉对话,关闭可视化也可以结束绘制,而不会顺手清空属于整个站点的状态。

页面暂时隐藏,又是另一种情况。标签页不在前台时,内容仍然存在,继续高频绘制却很少有意义。可以在可见性变化时停止循环,回来之后重新启动,并避免把隐藏期间的全部时间差一次性加入动画。

尺寸变化也会留下工作

Canvas 或图形组件经常需要观察容器尺寸。观察器应该跟着容器走,而不是随着每次渲染重复添加。尺寸变化后更新绘制区域,卸载时断开,才能避免已经移除的对象继续收到通知。

事件监听同样需要稳定的函数引用。添加和移除的目标、类型与回调应当一致,否则清理可能看起来执行了,实际却没有移除原来的监听。

这些细节看起来琐碎,但它们决定一个组件能否被安全地复用。组件越常见,生命周期边界越值得在实现时讲清楚,而不是等出现偶发卡顿再补救。

停止之后仍然可以有画面

用户关闭动效,不一定意味着图形区域应该空白。绘制一个静态状态之后停止循环,可以保留界面身份和内容层次,同时减少持续工作。静态图形与持续动画,是可以分开管理的两种能力。

同样,终止网络请求之后,输入和已经完成的历史仍然可以保留。结束某项工作,不应该无意中清空其他有价值的信息。清理需要准确,不只是彻底。

一个组件的质量,既体现在打开时的效果,也体现在结束时是否留下不属于自己的工作。给开始安排结束,给资源确定所有者,交互才能经得起反复使用。