当前位置: 首页 > news >正文

Vue3转React速查表

  • Vue: 基于可变数据 (Mutable)+自动依赖追踪(响应式系统)。
  • React: 基于不可变数据 (Immutable)+显式依赖数组(手动触发更新)。

1. 核心概念映射表 (Cheat Sheet)

| 功能 | Vue 3 (Composition API) | React (Hooks) | 关键差异点 |
| :--- | :--- | :--- | : |
|状态定义|const count = ref(0)|const [count, setCount] = useState(0)| Vue 直接修改count.value;React 必须调用setCount|
|计算属性|const double = computed(() => count.value * 2)|const double = useMemo(() => count * 2, [count])| React 需手动指定依赖[count]|
|副作用|watchEffect(() => { ... })
watch(source, cb)|useEffect(() => { ... }, [deps])| React 的useEffect同时涵盖 mount/update/unmount |
|清理副作用|onUnmounted(() => ...)
(在 watch 中 return) |useEffect(() => { return () => ... }, [])| 清理函数在 return 中返回 |
|模板/JSX|<template>{{ count }}</template>|return <div>{count}</div>| React 直接用 JS 表达式,无插值符号{{ }}|
|条件渲染|v-if="isOk"|{ isOk && <div>...</div> }| React 使用逻辑与运算符或三元表达式 |
|列表渲染|v-for="item in list" :key="item.id"|{list.map(item => <div key={item.id}>)}| React 必须显式写mapkey|
|事件绑定|@click="handleClick"|onClick={handleClick}| React 用驼峰onClick,传函数引用 (不调用) |
|双向绑定|v-model="text"|value={text} onChange={(e) => setText(e.target.value)}| React 没有内置指令,需手动绑定 value + onChange |
|组件通信|props,emit('event')|props,callback props| React 单向数据流,子传父通过回调函数 |
|插槽|<slot />,<slot name="header">|props.children,props.header| React 把插槽当作 props 传递 (通常是 children) |
|生命周期|onMounted,onUpdated|useEffect(..., [])(Mount)
useEffect(..., [deps])(Update) | React 将生命周期合并进useEffect|
|样式绑定|:class="{ active: isActive }"|className={isActive ? 'active' : ''}| React 用className,逻辑需用 JS 三元或库 (clsx) |
|Refs/DOM|const el = ref(null)
<div ref="el">|const el = useRef(null)
<div ref={el}>| Vue ref 取值.value;React ref 取值.current|

2. 代码实战对比 (Side-by-Side)

场景 A: 基础计数器 (State & Events)
Vue 3:
<script setup> import { ref } from 'vue'; const count = ref(0); const increment = () => count.value++; </script> <template> <button @click="increment">Count: {{ count }}</button> </template>
React:
import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); const increment = () => setCount(prev => prev + 1); // 习惯用函数式更新 return ( <button onClick={increment}>Count: {count}</button> ); }

注意: React 中事件处理函数不要加括号(),除非你需要传参(此时用箭头函数包裹)。

场景 B: 异步数据获取 (Effects)
Vue 3:
<script setup> import { ref, onMounted } from 'vue'; const data = ref(null); const loading = ref(false); const fetchData = async () => { loading.value = true; data.value = await fetch('/api').then(r => r.json()); loading.value = false; }; onMounted(fetchData); </script>
React:
import { useState, useEffect } from 'react'; function DataFetcher() { const [data, setData] = useState(null); const [loading, setLoading] = useState(false); useEffect(() => { let isMounted = true; // 防止组件卸载后更新状态 const fetchData = async () => { setLoading(true); const res = await fetch('/api'); const json = await res.json(); if (isMounted) setData(json); setLoading(false); }; fetchData(); // 清理函数 (对应 onUnmounted) return () => { isMounted = false; }; }, []); // 空依赖数组 = 只在挂载时运行 return <div>{loading ? 'Loading...' : JSON.stringify(data)}</div>; }
场景 C: 父子组件通信 (Props & Callbacks)
Vue 3:
<!-- Child.vue --> <script setup> defineProps(['msg']); const emit = defineEmits(['update']); </script> <template> <button @click="emit('update', 'new value')">{{ msg }}</button> </template>
React:
// Child.jsx function Child({ msg, onUpdate }) { return ( <button onClick={() => onUpdate('new value')}>{msg}</button> ); } // Parent.jsx <Child msg="Hello" onUpdate={(val) => console.log(val)} />

关键点: React 没有$emit。父组件传递一个函数作为 prop,子组件调用该函数。

场景 D: 列表与条件渲染
Vue 3:
<template> <ul v-if="items.length"> <li v-for="item in items" :key="item.id"> {{ item.name }} </li> </ul> <p v-else>No items</p> </template>
React:
return ( <> {items.length > 0 ? ( <ul> {items.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> ) : ( <p>No items</p> )} </> );

技巧: 推荐使用clsxclassnames库来处理复杂的 class 拼接,替代 Vue 的对象语法。

3. 生态库迁移指南 (Vue -> React)

类别Vue 3 生态React 推荐生态 (2026标准)备注
路由Vue RouterReact Router v6/v7 或 Next.js App RouterNext.js 是首选,内置路由
状态管理Pinia / VuexZustand (最流行), Redux Toolkit, JotaiZustand 最像 Pinia,简单无样板
HTTPAxios / VueUseTanStack Query (React Query), AxiosReact Query 是服务端状态管理的神器
表单VeeValidate / FormKitReact Hook Form, Zod (校验)React Hook Form 性能极佳
UI 组件库Element Plus / AntDVAnt Design, MUI, Shadcn/ui (最火)Shadcn/ui 是复制代码而非安装包,极度灵活
工具函数VueUseLodash, date-fns, clsxReact 没有官方工具集,社区组合使用
CSS 方案Scoped CSS / SCSSTailwind CSS (主流), CSS Modules, Styled-componentsTailwind 在 React 生态中占据统治地位

4. 避坑指南:Vue 开发者转 React 的常见错误

  1. 直接修改 State
    • Vue:count.value++
    • React:count++❌ (不会触发重渲染)
    • React:setCount(count + 1)
  2. 在 Render 函数中执行副作用
    • 不要在组件函数体直接写fetch()console.log('render')(除非受控),这会导致无限循环。必须放在useEffect中。
  3. 依赖数组遗漏⚠️
    • Vue 自动追踪依赖。
    • React 必须手动在useEffectuseMemo[]中列出所有用到的变量,否则会遇到“闭包陷阱”(拿到旧值)。
  4. Key 的使用⚠️
    • Vue 有时不写 key 也能跑。
    • React必须map生成的列表提供稳定的key(不要用 index,除非列表静态)。
  5. Ref 的取值⚠️
    • Vue:myRef.value
    • React:myRef.current(且修改ref.current不会触发重渲染,它用于存储可变但不需要视图更新的值)。
http://www.jsqmd.com/news/495142/

相关文章:

  • 当贝D7X Pro亮相315,网友:这配置放在三千元是降维打击!
  • windows通过网线连接linux开发板使用tftp传输文件
  • 三方备付金·非同充值+非同代付+D0秒到
  • 本地部署 vs 云端:OpenClaw 隐私安全机制深度拆解
  • SOM-BP多变量时序预测:已调试好的MATLAB程序(含清晰注释与评价指标)
  • LXQt 桌面配置不完全指南
  • 三相光伏并网逆变器方案:基于TMS32F2808主控芯片,包含接口板、电源板等多元化组件的综合...
  • GC Roots与可达性分析——对象是如何被标记存活的?
  • 每日一题:Span<T>和Memory<T>
  • 万爱通礼品卡闲置不用?教你选择最靠谱的线上回收渠道 - 团团收购物卡回收
  • 网页编辑器如何优化WangEditor的Word粘贴功能?
  • 从“安全孤岛”到“信任基石”:ibbot智体机灵如何重新定义AI智能体的安全范式
  • TCP/IP转EtherNet/IP 协议转换 罗克韦尔PLC与视觉设备交互
  • Simulink十四自由度整车模型
  • 【重磅】优质的朋友圈广告排名前十 - 服务品牌热点
  • 【从零入门23种设计模式24】行为型之访问者模式
  • 给AI老板植入幻觉:让它自认是饮水机
  • OpenAI 新模型 GPT - 5.4 系列:小身材能否撬动大市场?
  • 总结GRG石膏制品选购要点,天津好用的品牌有哪些 - mypinpai
  • 探索 FDTD 算法仿真超透镜:从参数调整到聚焦实现
  • 黑马点评-用JMeter测试缓存重建时,HTTP请求的响应结果的data为空
  • 二分题目集
  • 2026年GRG石膏制品优质供应商推荐,费用怎么算 - 工业设备
  • 项目实训(一):项目基础框架与 FastAPI 后端创建
  • 深度解析 `utf8mb4` 和 `utf8mb4_unicode_ci`:从原理到实战,避坑指南全解析
  • SSR驱动220V需TVS/MOV而非RCD
  • 2026年黑龙江高性价比二手房翻新企业排名,值得选的品牌 - 工业推荐榜
  • Claude国内镜像站实测:可扩展监督与宪法AI,推理架构的范式革命
  • 关于防抖和节流
  • 操作步骤分享:DeepSeek转Word文档的正确步骤