请先看实例项目分析:Vue3 与 React 构建外卖平台项目对比分析
目录
核心语法差异
1. 模板语法 vs JSX
Vue3 - 模板语法(Template-based)
<template>
<div class="food-item">
<img :src="food.image" :alt="food.name" />
<h4>{{ food.name }}</h4>
<span>¥{{ food.price }}</span>
<button @click="increase">+</button>
</div>
</template>
特点:
- 使用 HTML 模板,通过指令绑定数据
-
{{ }}插值表达式 -
:src属性绑定(v-bind 简写) -
@click事件绑定(v-on 简写) - 模板与逻辑分离,更接近传统 HTML
React - JSX(JavaScript XML)
function FoodItem({ food, onIncrease }) {
return (
<div className="food-item">
<img src={food.image} alt={food.name} />
<h4>{food.name}</h4>
<span>¥{food.price}</span>
<button onClick={onIncrease}>+</button>
</div>
);
}
特点:
- JSX 是 JavaScript 的语法扩展
- 使用
{}嵌入 JavaScript 表达式 - 属性使用驼峰命名(
className而非class) - 事件处理函数作为 props 传递
- 模板与逻辑混合,更接近 JavaScript
核心差异:
- Vue:声明式模板,指令系统,更接近 HTML
- React:JSX 是 JavaScript,需要编译,更灵活但学习曲线陡
组件定义方式
2. Vue3 Composition API vs React Hooks
Vue3 - Composition API(setup 语法糖)
<script setup>
import { ref, computed } from 'vue';
import { useCartStore } from '../stores/cart';
const props = defineProps({
food: {
type: Object,
required: true,
},
shopId: {
type: [Number, String],
required: true,
},
});
const cartStore = useCartStore();
const quantity = computed(() => {
const item = cartStore.items.find(
(item) => item.shopId === props.shopId && item.foodId === props.food.id
);
return item ? item.quantity : 0;
});
const increase = () => {
cartStore.addItem(props.shopId, props.shopName, props.food);
};
</script>
特点:
-
<script setup>语法糖,自动暴露变量和函数 -
defineProps定义 props,类型检查 - 响应式数据使用
ref、reactive - 计算属性使用
computed - 代码组织更灵活,逻辑可复用
React - Hooks
import { useMemo } from 'react';
import { useCartStore } from '../stores/cart';
function FoodItem({ food, shopId, shopName }) {
const cartStore = useCartStore();
const quantity = useMemo(() => {
const item = cartStore.items.find(
(item) => item.shopId === shopId && item.foodId === food.id
);
return item ? item.quantity : 0;
}, [cartStore.items, shopId, food.id]);
const increase = () => {
cartStore.addItem(shopId, shopName, food);
};
return (
// JSX...
);
}
特点:
- 函数组件 + Hooks
- Props 作为函数参数
-
useMemo实现计算属性 - 需要手动管理依赖数组
- 所有逻辑都在函数体内
核心差异:
- Vue:setup 语法糖,自动处理,更简洁
- React:显式使用 Hooks,需要理解闭包和依赖
状态管理
3. Pinia vs Zustand/Redux
Vue3 - Pinia Store
// stores/cart.js
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export const useCartStore = defineStore('cart', () => {
// 状态
const items = ref([]);
// 方法
const addItem = (shopId, shopName, food) => {
const existingItem = items.value.find(
item => item.shopId === shopId && item.foodId === food.id
);
if (existingItem) {
existingItem.quantity += 1;
} else {
items.value.push({
shopId,
shopName,
foodId: food.id,
foodName: food.name,
foodPrice: food.price,
quantity: 1
});
}
};
// 计算属性
const totalCount = computed(() => {
return items.value.reduce((sum, item) => sum + item.quantity, 0);
});
const totalPrice = computed(() => {
return items.value.reduce((sum, item) => sum + item.foodPrice * item.quantity, 0);
});
return {
items,
addItem,
totalCount,
totalPrice
};
});
使用方式:
<script setup>
import { useCartStore } from '../stores/cart';
const cartStore = useCartStore();
// 直接使用,自动响应式
console.log(cartStore.totalCount);
</script>
特点:
- 基于 Vue 的响应式系统
- 自动追踪依赖
- 可以直接修改状态(通过
.value) - 计算属性自动缓存
React - Zustand Store
// stores/cart.js
import { create } from 'zustand';
export const useCartStore = create((set, get) => ({
// 状态
items: [],
// 方法
addItem: (shopId, shopName, food) => {
const items = get().items;
const existingItem = items.find(
item => item.shopId === shopId && item.foodId === food.id
);
if (existingItem) {
set({
items: items.map(item =>
item.shopId === shopId && item.foodId === food.id
? { ...item, quantity: item.quantity + 1 }
: item
)
});
} else {
set({
items: [...items, {
shopId,
shopName,
foodId: food.id,
foodName: food.name,
foodPrice: food.price,
quantity: 1
}]
});
}
},
// Getter(需要手动计算)
getTotalCount: () => {
return get().items.reduce((sum, item) => sum + item.quantity, 0);
},
getTotalPrice: () => {
return get().items.reduce((sum, item) => sum + item.foodPrice * item.quantity, 0);
}
}));
使用方式:
import { useCartStore } from '../stores/cart';
function Cart() {
const items = useCartStore(state => state.items);
const addItem = useCartStore(state => state.addItem);
const totalCount = useCartStore(state => state.getTotalCount());
// 需要手动选择需要的状态
return <div>{totalCount}</div>;
}
特点:
- 不可变更新模式
- 需要手动选择订阅的状态
- Getter 需要手动调用
- 更符合函数式编程
核心差异:
- Vue:响应式系统,自动追踪,直接修改
- React:不可变更新,手动选择,函数式
响应式原理
4. Proxy vs 手动更新
Vue3 - 基于 Proxy 的响应式
// Vue3 内部实现原理(简化版)
const reactive = (target) => {
return new Proxy(target, {
get(target, key) {
// 依赖收集
track(target, key);
return target[key];
},
set(target, key, value) {
target[key] = value;
// 触发更新
trigger(target, key);
return true;
}
});
};
// 使用
const state = reactive({ count: 0 });
state.count++; // 自动触发更新
在组件中的表现:
<script setup>
const count = ref(0);
// 修改 count.value 时,所有使用 count 的地方自动更新
</script>
<template>
<div>{{ count }}</div> <!-- 自动更新 -->
</template>
React - 手动触发更新
// React 使用 setState 触发更新
function Counter() {
const [count, setCount] = useState(0);
// 必须调用 setCount 才能触发更新
const increment = () => {
setCount(count + 1); // 手动触发重新渲染
};
return <div>{count}</div>;
}
核心差异:
- Vue:自动追踪依赖,修改即更新
- React:手动调用 setState,显式更新
生命周期与副作用
5. 生命周期对比
Vue3 - 生命周期 Hooks
<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue';
const shop = ref(null);
const foods = ref([]);
// 组件挂载
onMounted(() => {
shop.value = getShopById(route.params.id);
foods.value = getFoodsByShopId(route.params.id);
});
// 组件卸载
onUnmounted(() => {
// 清理工作
});
// 监听变化
watch(() => route.params.id, (newId) => {
// 路由参数变化时执行
shop.value = getShopById(newId);
foods.value = getFoodsByShopId(newId);
});
</script>
React - useEffect Hook
import { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
function ShopDetail() {
const { id } = useParams();
const [shop, setShop] = useState(null);
const [foods, setFoods] = useState([]);
// 组件挂载和 id 变化时执行
useEffect(() => {
setShop(getShopById(id));
setFoods(getFoodsByShopId(id));
// 清理函数(可选)
return () => {
// 清理工作
};
}, [id]); // 依赖数组
return (
// JSX...
);
}
核心差异:
- Vue:多个生命周期函数,职责明确
- React:一个
useEffect处理所有副作用,需要依赖数组
事件处理
6. 事件绑定方式
Vue3 - 指令绑定
<template>
<button @click="handleClick">点击</button>
<button @click.stop="handleClick">阻止冒泡</button>
<button @click.prevent="handleSubmit">阻止默认</button>
<input @keyup.enter="handleSearch" />
</template>
<script setup>
const handleClick = () => {
console.log('clicked');
};
</script>
特点:
- 指令系统,语法简洁
- 修饰符(
.stop,.prevent,.enter)方便
React - 函数传递
function Component() {
const handleClick = (e) => {
e.stopPropagation(); // 手动阻止冒泡
console.log('clicked');
};
const handleSubmit = (e) => {
e.preventDefault(); // 手动阻止默认
};
const handleKeyUp = (e) => {
if (e.key === 'Enter') {
handleSearch();
}
};
return (
<>
<button onClick={handleClick}>点击</button>
<input onKeyUp={handleKeyUp} />
</>
);
}
特点:
- 标准 DOM 事件,需要手动处理
- 更灵活但代码更多
条件渲染与列表渲染
7. 渲染语法对比
Vue3 - 指令渲染
<template>
<!-- 条件渲染 -->
<div v-if="shop">商家信息</div>
<div v-else>加载中...</div>
<!-- 列表渲染 -->
<div v-for="food in foods" :key="food.id">
{{ food.name }}
</div>
<!-- 条件显示 -->
<span v-if="quantity > 0">{{ quantity }}</span>
</template>
React - 三元运算符和 map
function Component({ shop, foods }) {
return (
<>
{/* 条件渲染 */}
{shop ? (
<div>商家信息</div>
) : (
<div>加载中...</div>
)}
{/* 列表渲染 */}
{foods.map(food => (
<div key={food.id}>
{food.name}
</div>
))}
{/* 条件显示 */}
{quantity > 0 && <span>{quantity}</span>}
</>
);
}
核心差异:
- Vue:指令系统,更声明式
- React:JavaScript 表达式,更灵活
样式处理
8. 样式作用域
Vue3 - Scoped CSS
<style scoped>
.food-item {
padding: 15px;
}
</style>
特点:
-
scoped自动添加唯一属性选择器 - 样式隔离,不会影响其他组件
- 支持 CSS 变量
React - CSS Modules / Styled-components
// CSS Modules
import styles from './FoodItem.module.css';
function FoodItem() {
return <div className={styles.foodItem}>...</div>;
}
// 或 Styled-components
import styled from 'styled-components';
const FoodItem = styled.div`
padding: 15px;
`;
function Component() {
return <FoodItem>...</FoodItem>;
}
特点:
- 需要额外配置或库
- 更灵活但需要学习成本
路由管理
9. Vue Router vs React Router
Vue3 - Vue Router
<script setup>
import { useRoute, useRouter } from 'vue-router';
const route = useRoute();
const router = useRouter();
// 获取参数
const shopId = route.params.id;
// 导航
router.push('/shop/1');
</script>
<template>
<router-view />
</template>
React - React Router
import { useParams, useNavigate } from 'react-router-dom';
function Component() {
const { id } = useParams();
const navigate = useNavigate();
// 导航
navigate('/shop/1');
return <div>Shop ID: {id}</div>;
}
核心差异:
- 语法相似,但 API 略有不同
- Vue Router 更集成,React Router 更灵活
思维模式差异
10. 编程范式对比
Vue3 - 选项式 + 声明式
思维特点:
- 数据驱动视图:修改数据,视图自动更新
- 指令系统:通过指令声明式描述行为
- 响应式系统:自动追踪依赖,无需手动管理
- 渐进式框架:可以逐步采用,学习曲线平缓
代码示例:
<script setup>
// 声明数据
const count = ref(0);
// 声明方法
const increment = () => {
count.value++; // 修改数据,视图自动更新
};
</script>
<template>
<!-- 声明式模板 -->
<button @click="increment">{{ count }}</button>
</template>
React - 函数式 + 命令式
思维特点:
- 组件即函数:一切都是函数,函数式编程
- 不可变数据:通过 setState 创建新状态
- 显式更新:需要手动触发重新渲染
- JavaScript 优先:JSX 就是 JavaScript
代码示例:
function Counter() {
// 使用 Hook 管理状态
const [count, setCount] = useState(0);
// 函数式更新
const increment = () => {
setCount(prev => prev + 1); // 显式更新
};
// 返回 JSX(JavaScript)
return (
<button onClick={increment}>{count}</button>
);
}
实际项目对比
购物车功能实现
Vue3 实现
<!-- FoodItem.vue -->
<template>
<div class="food-item">
<h4>{{ food.name }}</h4>
<span>¥{{ food.price }}</span>
<div class="actions">
<button v-if="quantity > 0" @click="decrease">-</button>
<span v-if="quantity > 0">{{ quantity }}</span>
<button @click="increase">+</button>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue';
import { useCartStore } from '../stores/cart';
const props = defineProps({
food: Object,
shopId: [Number, String],
shopName: String
});
const cartStore = useCartStore();
// 计算属性自动响应
const quantity = computed(() => {
return cartStore.items.find(
item => item.shopId === props.shopId && item.foodId === props.food.id
)?.quantity || 0;
});
const increase = () => {
cartStore.addItem(props.shopId, props.shopName, props.food);
};
const decrease = () => {
cartStore.decreaseItem(props.shopId, props.food.id);
};
</script>
React 实现
// FoodItem.jsx
import { useMemo } from 'react';
import { useCartStore } from '../stores/cart';
function FoodItem({ food, shopId, shopName }) {
const cartStore = useCartStore();
// 需要手动管理依赖
const quantity = useMemo(() => {
return cartStore.items.find(
item => item.shopId === shopId && item.foodId === food.id
)?.quantity || 0;
}, [cartStore.items, shopId, food.id]);
const increase = () => {
cartStore.addItem(shopId, shopName, food);
};
const decrease = () => {
cartStore.decreaseItem(shopId, food.id);
};
return (
<div className="food-item">
<h4>{food.name}</h4>
<span>¥{food.price}</span>
<div className="actions">
{quantity > 0 && <button onClick={decrease}>-</button>}
{quantity > 0 && <span>{quantity}</span>}
<button onClick={increase}>+</button>
</div>
</div>
);
}
总结对比表
| 特性 | Vue3 | React |
|---|---|---|
| 模板语法 | HTML 模板 + 指令 | JSX (JavaScript) |
| 响应式 | Proxy 自动追踪 | 手动 setState |
| 状态管理 | Pinia (响应式) | Zustand/Redux (不可变) |
| 组件定义 | <script setup> |
函数组件 + Hooks |
| 生命周期 | 多个生命周期函数 | useEffect + 依赖数组 |
| 事件处理 | 指令修饰符 | 标准 DOM 事件 |
| 样式 | Scoped CSS | CSS Modules / Styled |
| 学习曲线 | 平缓 | 陡峭 |
| 性能 | 自动优化 | 需要手动优化 |
| 生态 | Vue 生态 | React 生态 |
选择建议
选择 Vue3 如果:
- 团队更熟悉 HTML/CSS
- 需要快速开发,学习曲线平缓
- 喜欢声明式、数据驱动的开发方式
- 需要自动响应式更新
选择 React 如果:
- 团队更熟悉 JavaScript
- 需要更大的生态系统和社区
- 喜欢函数式编程
- 需要更灵活的架构
代码示例文件
本项目的 Vue3 实现位于:
- 组件:
src/components/ - 页面:
src/views/ - 状态管理:
src/stores/cart.js - 路由:
src/router/index.js
对应的 React 实现可以参考上述代码示例进行转换。
————————————————————————————————————————————————
那么如果想要同时学好两种框架,应该怎么做呢?同时学习 Vue3 和 React 完整指南如下(可供参考):
目录
学习策略
1. 先学一个,再学另一个(推荐)
为什么?
- 避免概念混淆
- 建立完整的知识体系
- 更容易理解框架设计思想
建议顺序:
-
先学 Vue3(如果更熟悉 HTML/CSS)
- 学习曲线平缓
- 更接近传统 Web 开发
- 自动响应式,减少心智负担
-
再学 React(如果更熟悉 JavaScript)
- 函数式编程思维
- 更大的生态系统
- 更灵活但需要更多手动管理
2. 对比学习法(进阶)
适用人群:
- 已有一定前端基础
- 想快速掌握两个框架
- 需要做技术选型
方法:
- 用同一个项目分别用两个框架实现
- 对比相同功能的实现方式
- 理解设计理念差异
学习路径规划
阶段一:基础语法(2-3周)
Vue3 学习重点
-
模板语法
- 插值表达式
{{ }} - 指令系统(v-if, v-for, v-bind, v-on)
- 事件处理
- 插值表达式
-
组件基础
- 单文件组件(SFC)
- Props 和 Emits
-
<script setup>语法
-
响应式数据
-
ref()和reactive() -
computed()计算属性 -
watch()监听器
-
实践项目: Todo 列表应用
React 学习重点
-
JSX 语法
- JSX 基础
- 表达式嵌入
{} - 条件渲染和列表渲染
-
组件基础
- 函数组件
- Props 传递
- 组件组合
-
Hooks 基础
-
useState状态管理 -
useEffect副作用 -
useMemo和useCallback
-
实践项目: Todo 列表应用(用 React 重写)
阶段二:状态管理(2-3周)
Vue3 - Pinia
// 学习重点
- defineStore 定义 store
- ref/reactive 响应式状态
- computed 计算属性
- actions 方法定义
实践: 购物车功能
React - Zustand/Redux
// 学习重点
- create store
- 不可变更新模式
- 状态选择器
- 中间件使用
实践: 购物车功能(用 React 重写)
阶段三:路由管理(1-2周)
Vue3 - Vue Router
// 学习重点
- 路由配置
- useRoute / useRouter
- 路由守卫
- 动态路由
React - React Router
// 学习重点
- Routes / Route
- useParams / useNavigate
- 路由守卫
- 嵌套路由
实践: 多页面应用(首页、列表、详情)
阶段四:高级特性(3-4周)
Vue3
- 组件通信(provide/inject)
- 插槽(Slots)
- 过渡动画
- 自定义指令
- Teleport
React
- Context API
- Render Props / HOC
- 错误边界
- Suspense
- Portal
阶段五:生态工具(2-3周)
Vue3 生态
- Vite 构建工具
- VueUse 工具库
- Element Plus / Ant Design Vue
- Pinia 状态管理
React 生态
- Create React App / Vite
- React Query
- Material-UI / Ant Design
- Redux Toolkit / Zustand
对比学习法
方法一:功能对比表
创建一个对比表,记录相同功能在两个框架中的实现:
| 功能 | Vue3 实现 | React 实现 | 差异点 |
|---|---|---|---|
| 状态管理 | ref(0) |
useState(0) |
响应式 vs 不可变 |
| 计算属性 | computed() |
useMemo() |
自动依赖 vs 手动依赖 |
| 监听变化 | watch() |
useEffect() |
声明式 vs 命令式 |
| 事件处理 | @click |
onClick |
指令 vs 属性 |
方法二:项目对比实现
步骤:
- 选择一个项目(如:外卖平台)
- 先用 Vue3 实现完整功能
- 再用 React 实现相同功能
- 对比代码差异和实现思路
对比维度:
- 代码量
- 可读性
- 性能
- 开发体验
方法三:概念映射
建立概念映射关系,帮助记忆:
Vue3 → React
─────────────────────────────
ref() → useState()
computed() → useMemo()
watch() → useEffect()
v-if → 三元运算符
v-for → map()
@click → onClick
:class → className
<script setup> → 函数组件
实践项目建议
初级项目(建议顺序)
1. Todo 应用
Vue3 版本:
- 学习:响应式数据、事件处理、列表渲染
- 重点:
ref,v-for,@click
React 版本:
- 学习:useState, map, 事件处理
- 重点:状态更新、不可变数据
2. 计数器应用
对比点:
- 状态更新方式
- 事件处理方式
- 响应式机制
3. 天气查询应用
学习点:
- API 调用
- 异步处理
- 错误处理
中级项目
4. 购物车应用(本项目)
Vue3 实现重点:
- Pinia 状态管理
- 计算属性
- 组件通信
React 实现重点:
- Zustand/Redux 状态管理
- useMemo 优化
- Context API
5. 博客系统
学习点:
- 路由管理
- 数据获取
- 表单处理
高级项目
6. 实时聊天应用
学习点:
- WebSocket
- 实时更新
- 性能优化
7. 管理后台系统
学习点:
- 复杂状态管理
- 权限控制
- 数据可视化
常见混淆点
1. 响应式更新
❌ 错误理解
// Vue3 - 错误
const count = 0; // 不是响应式的
count++; // 不会触发更新
// React - 错误
const [count, setCount] = useState(0);
count++; // 不会触发更新,必须用 setCount
✅ 正确理解
// Vue3 - 正确
const count = ref(0);
count.value++; // 自动触发更新
// React - 正确
const [count, setCount] = useState(0);
setCount(count + 1); // 手动触发更新
2. 列表渲染 Key
Vue3
<div v-for="item in list" :key="item.id">
{{ item.name }}
</div>
React
{list.map(item => (
<div key={item.id}>
{item.name}
</div>
))}
共同点: 都需要 key,用于优化渲染性能
3. 条件渲染
Vue3
<div v-if="isVisible">显示</div>
<div v-show="isVisible">显示(CSS控制)</div>
React
{isVisible && <div>显示</div>}
{isVisible ? <div>显示</div> : null}
区别:
- Vue:
v-if条件渲染,v-showCSS 控制 - React: 都是条件渲染,需要 CSS 控制显示隐藏
4. 事件处理
Vue3
<button @click="handleClick">点击</button>
<button @click.stop="handleClick">阻止冒泡</button>
React
<button onClick={handleClick}>点击</button>
<button onClick={(e) => {
e.stopPropagation();
handleClick();
}}>阻止冒泡</button>
区别:
- Vue: 指令修饰符,语法简洁
- React: 标准 DOM 事件,需要手动处理
5. 样式处理
Vue3
<style scoped>
.component {
color: red;
}
</style>
React
// CSS Modules
import styles from './Component.module.css';
<div className={styles.component}>内容</div>
// 或 Styled-components
const Component = styled.div`
color: red;
`;
区别:
- Vue: 内置 scoped,开箱即用
- React: 需要配置或使用第三方库
学习资源推荐
Vue3 学习资源
官方文档
推荐教程
- Vue3 官方教程 - 最权威,最全面
- Vue Mastery - 视频教程,循序渐进
- Vue School - 系统化课程
实战项目
- Vue3 实战项目集合
- 本项目的 Vue3 实现
React 学习资源
官方文档
推荐教程
- React 官方教程 - 官方推荐,质量高
- React 官方 Beta 文档 - 最新 Hooks 教程
- Epic React - 付费但质量极高
实战项目
- React 实战项目集合
- 本项目的 React 示例代码
对比学习建议
找一些相同功能的项目做对比学习,或者通过一些现成的学习对比网站查阅分析,知晓其原理差异加上手动实操
学习时间规划
方案一:循序渐进(推荐)
总时长:10-12 周
| 阶段 | 时间 | Vue3 | React | 重点 |
|---|---|---|---|---|
| 第1-2周 | 基础语法 | ✅ | - | 先掌握一个框架 |
| 第3-4周 | 状态管理 | ✅ | - | 深入理解响应式 |
| 第5-6周 | 路由+项目 | ✅ | - | 完整项目实践 |
| 第7-8周 | React基础 | - | ✅ | 学习第二个框架 |
| 第9-10周 | React进阶 | - | ✅ | 状态管理+路由 |
| 第11-12周 | 对比学习 | ✅ | ✅ | 对比实现相同项目 |
方案二:并行学习(进阶)
总时长:8-10 周
| 周次 | Vue3 | React | 对比项目 |
|---|---|---|---|
| 第1-2周 | 基础语法 | 基础语法 | Todo 应用 |
| 第3-4周 | 状态管理 | Hooks | 计数器应用 |
| 第5-6周 | 路由 | 路由 | 多页面应用 |
| 第7-8周 | 项目实战 | 项目实战 | 购物车应用 |
| 第9-10周 | 高级特性 | 高级特性 | 完整项目对比 |
注意: 并行学习容易混淆,建议有一定基础后再采用
实战练习建议
练习 1:基础语法对比
任务: 实现一个简单的计数器
Vue3 版本:
<template>
<div>
<p>计数:{{ count }}</p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
const count = ref(0);
const increment = () => {
count.value++;
};
const decrement = () => {
count.value--;
};
</script>
React 版本:
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(count + 1);
};
const decrement = () => {
setCount(count - 1);
};
return (
<div>
<p>计数:{count}</p>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
对比点:
- 状态定义方式
- 更新方式
- 模板语法
练习 2:列表渲染对比
任务: 实现商品列表
Vue3 版本:
<template>
<div v-for="food in foods" :key="food.id">
<h3>{{ food.name }}</h3>
<p>¥{{ food.price }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
const foods = ref([
{ id: 1, name: '汉堡', price: 20 },
{ id: 2, name: '薯条', price: 15 }
]);
</script>
React 版本:
import { useState } from 'react';
function FoodList() {
const [foods] = useState([
{ id: 1, name: '汉堡', price: 20 },
{ id: 2, name: '薯条', price: 15 }
]);
return (
<>
{foods.map(food => (
<div key={food.id}>
<h3>{food.name}</h3>
<p>¥{food.price}</p>
</div>
))}
</>
);
}
练习 3:状态管理对比
任务: 实现购物车功能
Vue3 + Pinia:
// stores/cart.js
export const useCartStore = defineStore('cart', () => {
const items = ref([]);
const addItem = (food) => {
items.value.push(food);
};
const totalPrice = computed(() => {
return items.value.reduce((sum, item) => sum + item.price, 0);
});
return { items, addItem, totalPrice };
});
React + Zustand:
// stores/cart.js
export const useCartStore = create((set, get) => ({
items: [],
addItem: (food) => {
set({ items: [...get().items, food] });
},
getTotalPrice: () => {
return get().items.reduce((sum, item) => sum + item.price, 0);
}
}));
学习技巧
1. 建立知识地图
创建一个思维导图,记录两个框架的:
- 核心概念
- API 对比
- 使用场景
- 最佳实践
2. 做笔记对比
每次学习新概念时,记录:
- Vue3 的实现方式
- React 的实现方式
- 各自的优缺点
- 适用场景
3. 实践驱动学习
- 不要只看文档,要动手实践
- 用两个框架实现相同功能
- 对比代码差异和性能
4. 加入社区
- Vue 中文社区
- React 中文社区
- GitHub 关注相关项目
- 参与开源项目
5. 定期复习
- 每周回顾学习内容
- 对比两个框架的差异
- 总结最佳实践
常见问题 FAQ
Q1: 先学哪个框架?
- 如果更熟悉 HTML/CSS → 先学 Vue3
- 如果更熟悉 JavaScript → 先学 React
- 如果零基础 → 建议先学 Vue3(学习曲线平缓)
Q2: 会不会混淆两个框架?
- 初期可能会混淆,这是正常的
- 通过对比学习,建立清晰的概念映射
- 多实践,形成肌肉记忆
Q3: 需要学到什么程度?
- 基础: 能独立完成中小型项目
- 进阶: 理解框架原理,能优化性能
- 高级: 能根据项目需求选择合适框架
Q4: 如何选择使用哪个框架?
- Vue3: 快速开发、团队熟悉 HTML、需要自动响应式
- React: 大型项目、需要灵活架构、团队熟悉 JavaScript
Q5: 学习时间不够怎么办?
- 优先掌握一个框架到熟练程度
- 另一个框架了解核心概念即可
- 根据实际项目需求深入学习
学习检查清单
Vue3 掌握程度
- 理解模板语法和指令系统
- 掌握 Composition API
- 理解响应式原理(ref, reactive)
- 会使用 Pinia 进行状态管理
- 掌握 Vue Router 路由管理
- 能独立完成中等复杂度项目
React 掌握程度
- 理解 JSX 语法
- 掌握 Hooks(useState, useEffect 等)
- 理解函数式组件
- 会使用 Zustand/Redux 进行状态管理
- 掌握 React Router 路由管理
- 能独立完成中等复杂度项目
对比理解
- 能说出两个框架的核心差异
- 能根据场景选择合适框架
- 能用两个框架实现相同功能
- 理解各自的优缺点
总结
同时学习 Vue3 和 React 的关键:
- 循序渐进 - 先掌握一个,再学另一个
- 对比学习 - 用相同项目对比实现方式
- 实践为主 - 多写代码,少看文档
- 建立映射 - 理解概念对应关系
- 持续练习 - 定期复习和实战
记住:框架只是工具,核心是理解前端开发思想。 掌握了两个框架后,你会对前端开发有更深入的理解。
END