ustcthesis与Overleaf完美结合:云端LaTeX写作新体验
2026/5/11 7:29:51
工作这么多年,一直用的都是vue,对vue框架也最熟悉,但最近想深入学习react,之前也学过,只懂一点皮毛,对很多写法还是不理解,我就在想既然我比较熟悉vue,那能不能设计一份react和vue的转化总结,这样用理解vue的方式来学习react那就事半功倍了。
现在AI这么方便,我就把我的需求说给chatGPTchatGPTchatGPT
了,他帮我设计了一份 VueVue开发者 →ReactReact
转化总结与对照表和一份学习计划。
真的一目了然,特别好理解,在上周末我根据这两份计划很快的上手了react框架,也顺利完成一个小型的react项目,这次没有一知半解!
虽然AI可以帮我写代码,但我们自己还是得掌握,不然可能连代码都看不懂,怎么去进行调试呢
AI帮我们写90%,那剩下10%就要自己来了!
AI真的很好用,它可以帮助我们快速学习任何我们想学习的,还是使用最简单易上手的方式!
以下就是对照表以及学习计划了,希望对想快速上手react的小伙伴有点借鉴意义!
| 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 |
|---|---|
| onMounted | useEffect(() => {}, []) |
| onUpdated | useEffect(() => {}) |
| onUnmounted | useEffect(() => return cleanup, []) |
| onActivated | 无,需要自定义 |
| onDeactivated | 无,需要自定义 |
| beforeMount / beforeUpdate | 无(通常不需要) |
<script setup> onMounted(() => console.log("mounted")) onUnmounted(() => console.log("unmounted")) </script>useEffect(() => { console.log("mounted"); return () => console.log("unmounted"); }, []);| Vue | React 等价方案 | 特点 |
|---|---|---|
| Pinia |
Zustand
| 写法最像,轻量好用(推荐) | ||
| Vuex | Redux Toolkit | 官方推荐、企业级 |
| composables | 自定义 Hooks | 逻辑复用方式几乎一样 |
| reactive() | useState/useReducer | 响应式状态 |
Zustand 使用方式类似 Pinia,推荐入门 React 状态管理就用它。
示例:Zustand vs Pinia
export const useUserStore = defineStore('user', { state: () => ({ name: 'Echo' }), actions: { setName(name) { this.name = name } } })const useUserStore = create((set) => ({ name: "Echo", setName: (name) => set({ name }), }));几乎一模一样。
| Vue Router | React Router |
|---|---|
| routes 数组 | <Routes><Route/></Routes> |
| router.push() | useNavigate() |
| 获取参数 | useParams() |
| 路由守卫 | 自定义鉴权组件包裹 Route |
const routes = [ { path: '/user/:id', component: User } ]<Routes> <Route path="/user/:id" element={<User />} /> </Routes>读取参数:
const { id } = useParams()src/ components/ views/ store/ router/ composables/ assets/src/ components/ # 公共组件 pages/ # 页面级组件 hooks/ # 自定义 Hooks store/ # 状态管理(Zustand / Redux) router/ # 路由定义 services/ # API 请求封装 assets/Vue:
<v-if="ok">hello</v-if>React:
{ok && <div>hello</div>}Vue 自动追踪
React 必须写依赖数组
Vue compositions → React 自定义 Hooks
但事件改为父传回调函数
少魔法、少黑盒、更多掌控权。
npm create vite@latest react-basic --template react cd react-basic npm install npm run devimport { 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 对照:
<script setup> const count = ref(0) </script> <button @click="count++">{{ count }}</button>| Vue | React |
|---|---|
| onMounted | useEffect(() => {}, []) |
| onUpdated | useEffect(() => {}) |
| onUnmounted | return () => {} |
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>; }Vue 组合式 API 与 React 自定义 hook 是一样的概念。
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 }; }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> ); }src/ pages/ Home.jsx Detail.jsx main.jsx App.jsxnpm install react-router-domimport { 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> ); }import { useParams } from "react-router-dom"; export default function Detail() { const { id } = useParams(); return <h2>详情页面 - ID: {id}</h2>; }为了更像 Vue 的 Pinia,你会更喜欢Zustand。
npm install zustandimport { create } from "zustand"; export const useUserStore = create((set) => ({ name: "Echo", setName: (name) => set({ name }), }));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> ); }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;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 }; }做一个后台管理系统模版(React):