前言
工作这么多年,一直用的都是vue,对vue框架也最熟悉,但最近想深入学习react,之前也学过,只懂一点皮毛,对很多写法还是不理解,我就在想既然我比较熟悉vue,那能不能设计一份react和vue的转化总结,这样用理解vue的方式来学习react那就事半功倍了。
现在AI这么方便,我就把我的需求说给chatGPT了,他帮我设计了一份Vue 开发者 → React 转化总结与对照表和一份学习计划。
真的一目了然,特别好理解,在上周末我根据这两份计划很快的上手了react框架,也顺利完成一个小型的react项目,这次没有一知半解!
虽然AI可以帮我写代码,但我们自己还是得掌握,不然可能连代码都看不懂,怎么去进行调试呢?
AI帮我们写90%,那剩下10%就要自己来了!
AI真的很好用,它可以帮助我们快速学习任何我们想学习的,还是使用最简单易上手的方式!
以下就是对照表以及学习计划了,希望对想快速上手react的小伙伴有点借鉴意义!
核心思想对比
Vue
- 使用模板(HTML-like template)
- 自动依赖追踪的响应式系统
- 指令系统(v-if / v-for / v-model)
- 双向绑定常见
- 更"框架化",封装度高
React
- UI = f(state) 的函数式思想
- 使用 JSX(模板+JS融合)
- 没有自动依赖追踪,需要手动声明(useEffect)
- 单向数据流
- 更灵活、更偏底层
API 对照表
核心 API 对照
| Vue | React | 说明 |
|---|---|---|
data() |
useState |
声明组件状态 |
computed |
useMemo |
计算属性 |
watch |
useEffect |
监听值变化或模拟生命周期 |
| 方法(methods) | 普通函数 | 不需要特殊 API |
ref() |
useRef |
DOM 或变量引用 |
provide / inject |
createContext + useContext |
跨组件传递数据 |
v-model |
onChange + useState |
双向绑定自己实现 |
v-if |
JS 表达式(条件渲染) | { condition && <Component /> } |
v-for |
arr.map() |
列表渲染 |
| 组件通信(props) | props | 完全一致 |
| 子组件事件(emit) | 父传入回调函数 | 回调作为 props |
生命周期迁移
Vue → React 生命周期对照表
| Vue | React |
|---|---|
| onMounted | useEffect(() => {}, []) |
| onUpdated | useEffect(() => {}) |
| onUnmounted | useEffect(() => return cleanup, []) |
| onActivated | 无,需要自定义 |
| onDeactivated | 无,需要自定义 |
| beforeMount / beforeUpdate | 无(通常不需要) |
示例:Vue → React 生命周期对比
Vue
xml
<script setup>
onMounted(() => console.log("mounted"))
onUnmounted(() => console.log("unmounted"))
</script>
React
javascript
useEffect(() => {
console.log("mounted");
return () => console.log("unmounted");
}, []);
状态管理迁移
Vue → React 状态管理选择
| Vue | React 等价方案 | 特点 |
|---|---|---|
| Pinia | Zustand | 写法最像,轻量好用(推荐) |
| Vuex | Redux Toolkit | 官方推荐、企业级 |
| composables | 自定义 Hooks | 逻辑复用方式几乎一样 |
| reactive() | useState/useReducer | 响应式状态 |
Zustand(最适合 Vue 开发者)
Zustand 使用方式类似 Pinia,推荐入门 React 状态管理就用它。
示例:Zustand vs Pinia
Pinia
javascript
export const useUserStore = defineStore('user', {
state: () => ({ name: 'Echo' }),
actions: { setName(name) { this.name = name } }
})
Zustand
javascript
const useUserStore = create((set) => ({
name: "Echo",
setName: (name) => set({ name }),
}));
几乎一模一样。
路由迁移
Vue Router → React Router 对照表
| Vue Router | React Router |
|---|---|
| routes 数组 | <Routes><Route/></Routes> |
| router.push() | useNavigate() |
| 获取参数 | useParams() |
| 路由守卫 | 自定义鉴权组件包裹 Route |
Vue 路由
ini
const routes = [
{ path: '/user/:id', component: User }
]
React 路由
xml
<Routes>
<Route path="/user/:id" element={<User />} />
</Routes>
读取参数:
scss
const { id } = useParams()
项目结构对照
Vue 项目结构
css
src/
components/
views/
store/
router/
composables/
assets/
React 推荐结构
bash
src/
components/ # 公共组件
pages/ # 页面级组件
hooks/ # 自定义 Hooks
store/ # 状态管理(Zustand / Redux)
router/ # 路由定义
services/ # API 请求封装
assets/
思维模型转化总结
1. 模板 → JSX(最大的差异)
Vue:
ini
<v-if="ok">hello</v-if>
React:
css
{ok && <div>hello</div>}
2. 自动响应式 → 显式依赖声明
Vue 自动追踪
React 必须写依赖数组
3. 逻辑复用方式变化
Vue compositions → React 自定义 Hooks
4. 组件通信完全一致(props)
但事件改为父传回调函数
5. React 更纯粹、更 JavaScript 化
少魔法、少黑盒、更多掌控权。
学习计划(适合 Vue 开发者)
📘 阶段 1:核心理念与基础 JSX
⭐ 核心目标
- 理解 React 哲学(UI = f(state))
- 能用 JSX 编写组件、列表、事件
✅ 实战 1:Hello React + 计数器
1. 新建项目(Vite)
sql
npm create vite@latest react-basic --template react
cd react-basic
npm install
npm run dev
2. 编写一个计数器(App.jsx)
javascript
import { useState } from "react";
export default function App() {
const [count, setCount] = useState(0);
return (
<div style={{ padding: 20 }}>
<h1>计数器</h1>
<p>当前值:{count}</p>
<button onClick={() => setCount(count + 1)}>增加</button>
</div>
);
}
📝 Vue 对照:
xml
<script setup>
const count = ref(0)
</script>
<button @click="count++">{{ count }}</button>
🌱 实践任务
- 写一个 从 1 增加到 100 的进度条动画
- 写一个 列表渲染组件(todoList)
📘 阶段 2:Hooks 深入
⭐ 核心要点
- useState
- useEffect(替代 watch / 生命周期)
- useMemo / useCallback(性能)
- useRef(替代 Vue的模板 ref)
- 自定义 hooks(对 Vue 用户最重要)
✅ 实战 2:useEffect 生命周期模拟
Vue → React 生命周期对照
| Vue | React |
|---|---|
| onMounted | useEffect(() => {}, []) |
| onUpdated | useEffect(() => {}) |
| onUnmounted | return () => {} |
例子:监听窗口大小
javascript
import { useState, useEffect } from "react";
export default function WindowSize() {
const [size, setSize] = useState({ w: window.innerWidth, h: window.innerHeight });
useEffect(() => {
const onResize = () => {
setSize({ w: window.innerWidth, h: window.innerHeight });
};
window.addEventListener("resize", onResize);
return () => window.removeEventListener("resize", onResize);
}, []);
return <div>窗口大小:{size.w} x {size.h}</div>;
}
✅ 实战 3:自定义 Hook(重要)
Vue 组合式 API 与 React 自定义 hook 是一样的概念。
useFetch.js
scss
import { useState, useEffect } from "react";
export function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then((r) => r.json())
.then((json) => {
setData(json);
setLoading(false);
});
}, [url]);
return { data, loading };
}
使用它
javascript
import { useFetch } from "./useFetch";
export default function UserList() {
const { data, loading } = useFetch("https://jsonplaceholder.typicode.com/users");
if (loading) return <p>加载中...</p>;
return (
<ul>
{data.map((u) => <li key={u.id}>{u.name}</li>)}
</ul>
);
}
🌱 实践任务
- 写一个 useLocalStorage(key, defaultValue)
- 写一个 useCountdown(秒)
- 写一个 useDebounce(value, delay)
📘 阶段 3:React Router
✅ 项目结构
css
src/
pages/
Home.jsx
Detail.jsx
main.jsx
App.jsx
安装
npm install react-router-dom
✅ 实战 4:配置基础路由
javascript
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./pages/Home";
import Detail from "./pages/Detail";
export default function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/detail/:id" element={<Detail />} />
</Routes>
</BrowserRouter>
);
}
Detail.jsx
javascript
import { useParams } from "react-router-dom";
export default function Detail() {
const { id } = useParams();
return <h2>详情页面 - ID: {id}</h2>;
}
🌱 实践任务
- 写一个 商品列表页 + 商品详情页
- 点击列表项跳转到详情页
📘 阶段 4:状态管理
为了更像 Vue 的 Pinia,你会更喜欢 Zustand。
👉 为什么不用 Redux?
- Redux 心智负担大(action/reducer/immutable)
- Zustand 更像 Pinia:简单、轻巧、API优雅
📦 安装 Zustand
npm install zustand
✅ 实战 5:创建用户 store(类似 Pinia)
src/store/user.js
javascript
import { create } from "zustand";
export const useUserStore = create((set) => ({
name: "Echo",
setName: (name) => set({ name }),
}));
在组件里使用
javascript
import { useUserStore } from "../store/user";
export default function Profile() {
const { name, setName } = useUserStore();
return (
<div>
<p>用户名:{name}</p>
<input onChange={(e) => setName(e.target.value)} />
</div>
);
}
🌱 实践任务
- 给 store 增加:token / userInfo / logout
- 全局 Layout 读取用户信息
📘 阶段 5:接口请求与工程化
推荐:axios 封装 + useRequest Hook
✅ 实战 6:axios 封装
/src/api/request.js
javascript
import axios from "axios";
const request = axios.create({
baseURL: "https://api.example.com",
timeout: 8000,
});
request.interceptors.response.use((res) => res.data);
export default request;
使用 useRequest Hook(可复用)
javascript
import { useEffect, useState } from "react";
import request from "../api/request";
export function useRequest(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
request(url).then((res) => {
setData(res);
setLoading(false);
});
}, [url]);
return { data, loading };
}
📘 阶段 6:综合项目
做一个 后台管理系统模版(React) :
功能组成
- 登录页
- Layout 布局(侧边栏 + Header)
- react-router 路由守卫
- 表格 CRUD(增删改查)
- Zustand 全局状态(保存用户)