從 Vue 跳到 React 的開發心得 — 兩個框架的差異與轉換經驗
做前端這幾年,Vue 和 React 都有碰過。一開始是從 Vue 入門,後來工作上也接觸了 React 專案。這篇來分享一下在兩個框架之間轉換的心得,以及實際開發時感受到的差異。
為什麼要學 React
老實說,Vue 用得很順手的時候,一開始對學 React 沒有太大的動力。但後來發現幾個現實的考量:
- 工作機會:看職缺的時候,React 的需求量確實比 Vue 多
- 生態系:React 的社群資源和第三方套件非常豐富
- 技術視野:多學一個框架可以用不同角度思考問題
而且 Vue 和 React 的核心概念其實很類似,轉換的門檻沒有想像中高,尤其是到了 Vue 3 時代,Composition API 的概念都和 React Hooks 很像。
最明顯的差異:模板 vs JSX
Vue 用的是 template 語法,長這樣:
<template>
<div>
<h1>{{ title }}</h1>
<ul>
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</ul>
<button @click="handleClick">點我</button>
</div>
</template>
React 用的是 JSX,邏輯和 UI 混在一起:
function MyComponent() {
return (
<div>
<h1>{title}</h1>
<ul>
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
<button onClick={handleClick}>點我</button>
</div>
);
}
剛開始看 JSX 會覺得很亂,怎麼 HTML 跟 JavaScript 攪在一起。但寫久了發現,這種寫法其實很靈活,複雜的條件渲染反而比 v-if 直覺。
仔細想想,React 本質上其實就是 JavaScript 加上 JSX 語法而已。它沒有像 Vue 那樣有額外的模板語法(v-if、v-for、v-model),所有的邏輯都是用原生 JavaScript 來寫。這也是為什麼學 React 之前要先把 JavaScript 基礎打好——你需要熟悉 map、filter、三元運算子、解構賦值這些東西,因為 React 就是拿這些來處理 UI 邏輯的。
狀態管理的差異
Vue 3 的 Composition API 和 React Hooks 其實很像:
Vue 3:
const count = ref(0);
const doubled = computed(() => count.value * 2);
const increment = () => {
count.value++;
};
React:
const [count, setCount] = useState(0);
const doubled = useMemo(() => count * 2, [count]);
const increment = () => {
setCount(count + 1);
};
主要差異是 Vue 的 ref 是響應式的,改值直接 .value = xxx。React 的 useState 要用 setter function,而且是不可變的(immutable)。
一開始常常忘記用 setCount,直接寫 count++,然後畫面就不會更新。這個習慣要適應一下。
生命週期的對應
Vue 和 React 的生命週期可以這樣對應:
| Vue 3 | React |
|---|---|
onMounted | useEffect(() => {}, []) |
onUpdated | useEffect(() => {}) |
onUnmounted | useEffect 的 cleanup function |
watch | useEffect 搭配 dependency array |
React 把所有副作用都用 useEffect 來處理,一開始會覺得有點不直覺。但習慣之後,其實邏輯蠻清楚的——dependency array 決定什麼時候要重新執行。
Next.js vs Nuxt
如果要做 SSR,Vue 有 Nuxt,React 有 Next.js。兩個框架的概念很類似:
- 檔案系統路由
- 自動程式碼分割
- SSR / SSG / ISR 支援
- API Routes
用過 Nuxt 3 再去學 Next.js,上手很快。主要差異在一些 API 命名和寫法上。
資料抓取:
Nuxt 用 useFetch 或 useAsyncData:
const { data } = await useFetch("/api/posts");
Next.js 的 App Router 用 async component:
async function Page() {
const data = await fetch("/api/posts");
return <div>{/* ... */}</div>;
}
狀態管理工具
Vue 生態系用 Pinia,React 生態系選擇比較多:Redux、Zustand、Jotai、Recoil…
我自己比較喜歡 Zustand,寫法簡潔,跟 Pinia 的感覺有點像:
// Zustand
const useStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}));
// 使用
const { count, increment } = useStore();
比起 Redux 的 action、reducer、dispatch 那一套,Zustand 直接多了。
轉換時遇到的坑
1. 忘記 Immutable
React 的狀態更新要保持 immutable,不能直接修改原物件:
// ❌ 錯誤
const handleClick = () => {
items.push(newItem);
setItems(items); // 不會觸發更新
};
// ✅ 正確
const handleClick = () => {
setItems([...items, newItem]);
};
Vue 的響應式系統會幫你處理這些,React 要自己注意。
2. useEffect 的 Dependency Array
useEffect 的 dependency array 設錯,會造成無限迴圈或該更新的時候沒更新:
// ⚠️ 小心無限迴圈
useEffect(() => {
setCount(count + 1);
}, [count]); // count 變了就執行,執行又改 count...
3. Conditional Hooks
React Hooks 不能放在條件式裡面:
// ❌ 錯誤
if (isLoggedIn) {
const [user, setUser] = useState(null);
}
// ✅ 正確
const [user, setUser] = useState(null);
if (isLoggedIn) {
// 使用 user
}
這個規則一開始會覺得很奇怪,但這是 React Hooks 的設計限制。
哪個比較好?
這個問題沒有標準答案。兩個框架都很成熟,都能做出好的產品。
Vue 的優點:
- 學習曲線較平緩
- 官方工具鏈完整(Vite、Pinia、Vue Router 都是官方出品)
- 模板語法對設計師比較友善
React 的優點:
- 生態系更龐大
- 工作機會較多
- JSX 的靈活度更高
- 社群資源豐富
我自己是兩個都用,看專案需求決定。已經有 Vue 基礎的人,學 React 不會太困難,反過來也是。
給想學 React 的 Vue 開發者
-
先學好 JavaScript:React 比較需要紮實的 JS 基礎,特別是 array methods、解構、spread operator
-
接受 JSX:一開始會不習慣,但寫久了會發現它的好
-
理解 Immutable:這是 React 的核心觀念,一定要搞懂
-
不要硬套 Vue 思維:有些東西在 Vue 很自然,在 React 要換一種方式思考
-
從 Next.js 開始也行:如果已經會 Nuxt,直接學 Next.js 會很有帶入感,學得也快
結語
Vue 和 React 都是很棒的框架,沒有誰比較好的問題。多學一個框架可以拓展視野,也能增加求職的競爭力。
如果你跟我一樣是 Vue 起家的,不用怕學 React。核心概念很類似,主要是語法和一些設計理念的差異。適應期過了之後,就能兩邊都寫了。