组件的生命周期

React/Vue 框架到底是什么里我们写的计数器,从头到尾都显示在页面上。但真实的页面不是这样,一个页面由很多组件拼成,有的组件一直在(比如导航栏),有的组件出现一会儿就没了(比如弹窗,点个叉就关掉了)。

也就是说,组件是有「生死」的:它会被创建,也会被销毁。而有些代码对执行时机有要求,比如「组件出现之后启动一个定时器」「组件消失之前把定时器关掉」,你要是不清楚组件从生到死的过程,这种代码就写不对,写出来的 bug 还特别隐蔽。

组件从生到死的这个过程,就是生命周期(Lifecycle)。本文先把生命周期的几个阶段讲清楚,再讲 React 里专门跟生命周期打交道的 API:useEffect

AI 写代码时会很好地处理组件的生命周期,但是我们还是有必要了解这些基本知识,否则纯小白看到 React 代码里面函数套函数,返回值还是个函数,很容易懵。

组件的一生:挂载、更新、卸载

React 组件的一生可以分成三个阶段:

  • 挂载(Mount):组件第一次被渲染到页面上,从无到有
  • 更新(Update):state 或者 props 变了,React 重新渲染这个组件,页面内容跟着变
  • 卸载(Unmount):组件从页面上被移除,从有到无

「更新」你其实已经见过了:计数器里每点一次按钮,setCount 触发重新渲染,这就是一次更新。挂载和卸载还没见过,下面这个 demo 里,按钮可以控制计数器组件的显示和隐藏:

核心逻辑就是

{show && <Counter />}

这是 JSX 里常见的条件渲染写法:showtrue 时渲染 <Counter />,为 false 时什么都不渲染。

所以点「隐藏计数器」,Counter 组件就被卸载了;再点「显示计数器」,一个新的 Counter 组件被挂载出来。

动手试试

在上面的 demo 里点几次 +1,把计数器加到 5,然后点「隐藏计数器」再点「显示计数器」,你会发现计数器变回了 0。

计数器为什么归零了?因为组件卸载时,它的 state 会被一起销毁

count 这个状态是属于 Counter 组件的运行时内存数据,组件从页面上被移除,相关的运行时数据会被清理,React 就把它的 state 一起丢掉了。之后再挂载出来的是一个全新的 CounteruseState(0) 老老实实从初始值 0 开始。

这个特性就是 React 的规则:state 的寿命和组件一样长,组件卸载了,state 的值跟着被清理

把三个阶段串起来,一个组件的生命周期就是这样一条时间轴:

挂载 ──> 更新 ──> 更新 ──> ... ──> 更新 ──> 卸载
(出现)  (用户交互,state 变化)          (消失)

随着用户在页面上交互,React 会自动推进这条时间轴,你控制不了什么时候挂载、更新、卸载组件。

但你可以往时间轴上「挂」自己的代码,比如组件挂载时做点什么、卸载前做点什么、更新时做点什么,这就轮到 useEffect 出场了:

export default function Example() {
    const [time, setTime] = useState(new Date().toLocaleTimeString());

    useEffect(() => {
        // 这部分代码在组件挂载(创建)时执行一次


        return () => {
            // 这部分代码在组件卸载(销毁)时执行一次
        }
    }, []);

    useEffect(() => {
        // 这部分代码在组件挂载时,以及每次 time 变量发生变化时执行
    }, [time]);


    return <p>{time}</p>;
}

这个规则看起来有些绕,但都是固定的套路。而且 AI 写代码都会帮你处理好,你只需要了解这些套路,大概能看懂代码就行了。

下面用几个例子来看 React 的生命周期,以及 useEffect 的实际用法。