vue2和vue3以及react生命周期对比

2. 各阶段核心钩子 + 用途(Vue2/Vue3 对应)

阶段 Vue2 钩子 Vue3 组合式 API 钩子 核心用途 注意事项
创建阶段 beforeCreate 无(setup 替代) 实例刚初始化,data/methods/props 均未挂载,无法访问 几乎不用,仅特殊初始化(如自定义事件总线)
created setup 内部(最早) 实例初始化完成,data/methods/props 已挂载,可访问数据但 DOM 未生成 1. 发起初始化数据请求(无需等待 DOM);2. 初始化非 DOM 相关逻辑(如定时器)
挂载阶段 beforeMount onBeforeMount 模板编译完成,即将挂载到真实 DOM,$el 未生成 可修改数据(不会触发额外更新),不推荐操作 DOM
mounted onMounted 组件挂载到真实 DOM 完成,$el 可用 1. 操作真实 DOM(如初始化第三方库:ECharts、富文本);2. 绑定事件监听
更新阶段 beforeUpdate onBeforeUpdate 数据更新,虚拟 DOM 重新渲染前 读取当前 DOM 状态(如获取元素尺寸),不可修改数据(会触发无限更新)
updated onUpdated 数据更新,真实 DOM 重新渲染完成 操作更新后的 DOM(如滚动到指定位置),避免修改数据(易触发无限更新)
销毁阶段 beforeUnmount onBeforeUnmount 组件即将卸载,实例仍完整可用 核心:清理资源(取消定时器、解绑事件、取消请求、销毁第三方库实例)
unmounted onUnmounted 组件已卸载,实例销毁 极少用,仅确认资源清理完成(如日志上报)

3. 实战示例(Vue3 组合式 API)

vue

xml 复制代码
<script setup>
import { ref, onMounted, onUpdated, onBeforeUnmount } from 'vue';
import axios from 'axios';

const count = ref(0);
let timer = null;
let chart = null;

// 对应 created:初始化数据请求
const fetchData = async () => {
  const res = await axios.get('/api/data');
  console.log('初始化数据:', res.data);
};
fetchData();

// 对应 mounted:操作 DOM + 初始化第三方库
onMounted(() => {
  console.log('DOM 挂载完成');
  // 初始化 ECharts
  chart = echarts.init(document.getElementById('chart'));
  chart.setOption({ /* 配置 */ });
  // 绑定窗口事件
  window.addEventListener('resize', handleResize);
  // 启动定时器
  timer = setInterval(() => count.value++, 1000);
});

// 对应 updated:操作更新后的 DOM
onUpdated(() => {
  console.log('DOM 更新完成,当前count:', count.value);
});

// 对应 beforeUnmount:清理资源(核心!)
onBeforeUnmount(() => {
  console.log('组件即将卸载,清理资源');
  clearInterval(timer); // 清除定时器
  window.removeEventListener('resize', handleResize); // 解绑事件
  chart?.dispose(); // 销毁 ECharts 实例
  axios.CancelToken.source().cancel('请求取消'); // 取消未完成的请求
});

const handleResize = () => chart?.resize();
</script>

三、React 生命周期(类组件 + 函数组件)

React 类组件有明确的生命周期钩子,函数组件无原生生命周期,需通过 useEffect 模拟,核心阶段可对应到 Vue 的 "创建 - 挂载 - 更新 - 销毁"。

1. React 类组件生命周期(核心 6 个钩子)

阶段 类组件钩子 对应 Vue 阶段 核心用途
挂载阶段 constructor beforeCreate/created 初始化 state、绑定函数 this(如 this.handleClick = this.handleClick.bind(this)
componentDidMount mounted 1. 发起初始化数据请求;2. 操作 DOM;3. 绑定事件 / 初始化第三方库
更新阶段 shouldComponentUpdate 无(Vue 自动优化) 返回布尔值,控制是否触发重渲染(性能优化,可替代 React.memo)
componentDidUpdate updated 数据更新后操作 DOM(如依赖 props 变化重新请求数据)
销毁阶段 componentWillUnmount beforeUnmount 清理资源(取消定时器、解绑事件、取消请求)
错误捕获 componentDidCatch 无(Vue 用 errorCaptured) 捕获子组件抛出的错误,避免应用崩溃

2. React 函数组件(useEffect 模拟生命周期)

函数组件通过 useEffect依赖数组控制执行时机,对应类组件生命周期:

useEffect 写法 对应类组件钩子 核心用途
useEffect(() => {}, []) componentDidMount 组件挂载后执行(仅 1 次):请求数据、绑定事件、初始化第三方库
useEffect(() => {}, [dep]) componentDidUpdate 依赖项变化时执行:如 ID 变化重新请求数据
useEffect(() => { return () => {} }, []) componentWillUnmount 组件卸载前执行:清理资源(清除定时器、解绑事件)
useEffect(() => {}) 无(mount + update) 每次渲染后执行(不推荐,易引发性能问题)

3. 实战示例(React 函数组件)

jsx

javascript 复制代码
import { useState, useEffect } from 'react';
import axios from 'axios';

function UserList({ userId }) {
  const [list, setList] = useState([]);
  let timer = null;

  // 1. 对应 componentDidMount:挂载后请求数据 + 初始化
  useEffect(() => {
    // 发起请求
    const fetchData = async () => {
      const res = await axios.get(`/api/user/${userId}`);
      setList(res.data);
    };
    fetchData();

    // 绑定事件
    window.addEventListener('resize', handleResize);
    // 启动定时器
    timer = setInterval(() => console.log('定时器运行'), 1000);

    // 2. 对应 componentWillUnmount:卸载前清理资源
    return () => {
      clearInterval(timer);
      window.removeEventListener('resize', handleResize);
      axios.CancelToken.source().cancel('请求取消');
    };
  }, [userId]); // 3. 对应 componentDidUpdate:userId 变化重新执行

  // 4. 对应 componentDidUpdate:更新后操作 DOM
  useEffect(() => {
    if (list.length > 0) {
      console.log('列表更新完成,滚动到顶部');
      document.getElementById('list').scrollTop = 0;
    }
  }, [list]);

  const handleResize = () => console.log('窗口变化');

  return (
    <div id="list">
      {list.map(item => <div key={item.id}>{item.name}</div>)}
    </div>
  );
}

四、各阶段核心使用原则(通用)

1. 创建 / 挂载阶段(初始化)

  • 禁止操作 DOMcreated(Vue)/ constructor(React)阶段 DOM 未生成,操作 DOM 会报错;
  • 数据请求优先 :初始化数据请求可在 created(Vue)/ componentDidMount(React)中发起,无需等待 DOM;
  • 第三方库初始化 :必须在 DOM 挂载完成后(mounted/componentDidMount)执行(如 ECharts 需要 DOM 节点)。

2. 更新阶段(数据变化)

  • 避免无限循环 :在 updated/componentDidUpdate 中修改数据时,必须加条件判断(如对比新旧值);
  • 性能优化 :React 用 shouldComponentUpdate/React.memo,Vue 用 computed/watch 减少不必要的更新。

3. 销毁阶段(资源清理)

  • 核心必做:所有手动绑定的资源(定时器、事件监听、第三方库实例、未完成的请求)必须在此阶段清理,否则会导致内存泄漏;
  • 禁止修改状态:销毁阶段修改状态无意义(组件即将卸载,不会触发更新)。

五、Vue vs React 生命周期核心对应

Vue 钩子 React 类组件钩子 React 函数组件写法 核心场景
created constructor + componentDidMount useEffect (() => {}, []) 内部 初始化数据请求
mounted componentDidMount useEffect(() => {}, []) 操作 DOM、初始化第三方库
updated componentDidUpdate useEffect(() => {}, [dep]) 数据更新后操作 DOM
beforeUnmount componentWillUnmount useEffect(() => { return () => {} }, []) 清理资源

总结

  1. 核心阶段:所有框架的生命周期都可归纳为「创建→挂载→更新→销毁」4 大阶段,用途高度一致;
  2. 核心原则:初始化逻辑(数据请求)放创建 / 挂载阶段,DOM 操作放挂载 / 更新阶段,资源清理放销毁阶段;
  3. 写法差异 :Vue 有明确的生命周期钩子,React 类组件同理,函数组件需用 useEffect 模拟;
  4. 避坑重点:销毁阶段必须清理资源(防内存泄漏),更新阶段修改数据需加条件(防无限循环)。

简单记:生命周期的核心是 "在正确的时间做正确的事"------ 初始化找 "挂载",更新找 "更新",清理找 "销毁"。

相关推荐
北辰alk19 分钟前
Vue 数据响应式探秘:如何让数组变化无所遁形?
vue.js
San3029 分钟前
告别全局污染:深入解析现代前端的模块化 CSS 演进之路
css·vue.js·react.js
如果你好30 分钟前
# Vue 事件系统核心:createInvoker 函数深度解析
前端·javascript·vue.js
林恒smileZAZ33 分钟前
【Vue3】我用 Vue 封装了个 ECharts Hooks
前端·vue.js·echarts
前端小菜鸟也有人起40 分钟前
浏览器不支持vue router
前端·javascript·vue.js
奔跑的web.43 分钟前
Vue 事件系统核心:createInvoker 函数深度解析
开发语言·前端·javascript·vue.js
江公望1 小时前
VUE3中,reactive()和ref()的区别10分钟讲清楚
前端·javascript·vue.js
内存不泄露2 小时前
基于Spring Boot和Vue 3的智能心理健康咨询平台设计与实现
vue.js·spring boot·后端
xkxnq2 小时前
第一阶段:Vue 基础入门(第 11 天)
前端·javascript·vue.js
内存不泄露2 小时前
基于Spring Boot和Vue的在线考试系统设计与实现
vue.js·spring boot·后端