2.4 组件生命周期管理


2.4 组件生命周期管理

本节摘要:组件从创建、更新到销毁会经过一系列可预期的节点,即生命周期。把握好"数据加载放在挂载后、清理资源放在卸载前"这类时机,比硬背生命周期命名更有价值。本节把通用思想讲清,并预告 Hooks 时代的形态,具体语法交给第 3、4 章。

本节阅读目标
阅读完本节,你应当能够:

  1. 描绘组件生命周期的三个大阶段。
  2. 把"该在哪一步做数据加载、订阅、清理"这类问题对号入座。
  3. 理解类组件生命周期与函数式 Hook 只是同一思想的不同表面。

一、为什么需要"一生"的概念

组件不是一段永恒竖立的代码。随着它被创建、刷新、移除,它对外部资源的占用也在变化:发起网络请求、订阅事件流、申请定时器……如果不蹭着这些节点收尾,就会造成泄漏。生命周期恰是框架留给你的"在每个关键时机做事"的钩子。

二、三个大阶段

  • 挂载:组件被插入页面,此时适合做首次数据加载、建立订阅。
  • 更新:props 或状态变化导致重渲,此时可以做依赖变化后的副作用。
  • 卸载:组件被移出页面,此时适合释放订阅、清除定时器,把占用还原。

把三个阶段的"该做什么/别做什么"画成一张全景图。

图:组件生命周期全景与对应编程动作

图:组件生命周期全景与对应编程动作

三、比稿重点:时机法则

评审是否合理,重点是时机而不是存不存在。三条法则:

  1. 副作用就地释放:建立订阅的节点,就要在对称的卸载节点释放,别拖到组件都不知道还在不在。
  2. 更新时判断依赖:依赖变了再重做副作用,没变就别白忙,避免重复请求。
  3. 别在渲染里干重活:加载、订阅这类有副作用的动作要挂在对应生命周期/副作用钩子上,而不是直接写在渲染过程里,否则每次渲染都可能触发。

四、类组件 vs 函数式 Hook 的表与里

类组件把生命周期写成一串方法可读的名字与回调,早期前端都在用。React 的 Hooks 时代则用 useEffect 这类副作用 Hook 表达同一回事,把"时机"包装成了回调。Vue 类似:Options API 里的 beforeMount、mounted 等方法对应 Composition API 里的 onMounted 等。表面是两套拼写,里子都是这套"创建 → 更新 → 销毁"心智。

用 React Hook 写一个带订阅清理的例子,把"就地释放"这条法则落成看得见的代码:

function OnlineBadge({ userId }) { useEffect(() => { const off = subscribeOnline(userId); // 挂载后/依赖变化后建立订阅 return () => off(); // 卸载前对称释放,正是"就地在对称节点清理" }, [userId]); // 依赖数组:userId 变了才重建订阅 return <span>在线状态订阅中…</span>; }

这个函数组件你看不到 mounted/unmounted 这些名字,但 useEffect 首次运行对应"挂载后"、依赖数组变化后重跑对应"更新"、返回的清理函数对应"卸载前"。同一份时机,换了件 Hook 的外衣——这正是"表不同、里一样"最直接的证据。Vue 的 watchEffectonUnmounted 也只是把这套心智又换了个拼写。

五、经典陷阱速览

一个"该在哪一步做事"的实操判断顺序

把时机法则变成可执行的 checklist,每次写"要在某时刻做事"的组件时,按下面顺序走一遍就不会漏。先问"这件事是不是有副作用"——网络、订阅、定时器、改外部 DOM 都算,纯计算不算;若是副作用,再问"它在数据变化后还要不要重新做"——要则放进依赖驱动的回调里,不要则只在挂载时做一次;最后问"组件消失时要不要回收"——要就把回收函数也放在同一个对称点写干净。

拿这个顺序去套典型场景:数据请求跟着 id 变、又在卸载时作废——就是"副作用 + 按依赖重建 + 就地回收";一次性初始化 WebSocket 握手——就是"副作用 + 只挂载一次 + 卸载时断连";一个 DOM 尺寸监听——就是"副作用 + 别乱重建 + 记得移除"。三个问题问完,绝大多数"该在哪个钩子写"的纠结自然消失,比硬记十个钩子的名字靠谱得多。

  • 忘了清理定时器:页面关了定时器还在跑,白耗资源。订阅、请求、定时器三样都是要在卸载点"回头关灯"的对象。
  • 请求没做卸载保护:组件卸载后回调还想 setState,出现警告甚至闪错。连上一条看,根子都是"该关的没关、该挡的没挡"。
  • 依赖数组留空导致嗅不到更新:副作用只跑一次,后续 props 变了不响应。配齐依赖是责任,而不是让 lint 闭嘴的仪式。

这些坑的共性是"把时机写岔了",跟生命周期本身关系不大。真正能帮你的是始终带着三阶段视角:这段代码在挂载/更新/卸载时各该在哪一步跑,跑完要不要就地收尾。

六、用"进场与离场"的眼光看组件

生命周期不好记,是因为名字多、还老变。换个比喻一切顺了:把组件想成一次有借有还的"入场"。进场(挂载)时你借了什么,离场(卸载)时就还什么——订阅了得退订,定时器得清掉,请求的监听得拆除。这笔账在 React、Vue 里都一样,只是记账的语法不同。

什么时候这个类比会失效?当组件"还在场但数据源已经换人"时——比如下拉框从用户 A 切成用户 B,挂在同一组件里。此时不是"进场/离场",而是"换了个服务对象"。React 里靠依赖数组,Vue 里靠 watchEffect 的依赖变化,都让"订阅跟着服务对象走"。于是生命周期从不只是"挂载/卸载"两个端点,而是还包括"更新"这条中间轨道:它决定你的副作用在对象变化后要不要重建。把"入场→换人→离场"当成一条完整的主线去理解,比背一张表格更贴近真实编码时的取舍。

这种"有借有还"的眼光还能帮你判断一段副作用该不该上钩子:凡是"会占用外部资源、且组件没了就该归还"的逻辑,都值得放进生命周期/副作用钩子,并在卸载点写好归还。而纯计算、纯展示的逻辑,离钩子越远越清爽。判断的出发点永远是"这笔资源是谁借的、组件消失时要不要还",而不是某个钩子的名字。

本节要点回顾

  • 三阶段:挂载、更新、卸载,对应不同职责。
  • 三条时机法则:就地清、按依赖来、别在渲染里干重活。
  • 表里关系:类生命周期与 Hook 是同一思想的两种写法。
  • 记三个坑:定时器泄漏、卸载后更新、依赖数组使用不当。

生命周期在 React 与 Vue 有各自的具体钩子名,第 3、4 章的对应节会逐个落地。下一节先讲两类大家日常最频繁碰到的界面行为:事件处理,以及条件、列表渲染。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U