快搜阅读器
69.16M · 2026-03-18
React (package.json):
{
"dependencies": {
"react": "^19.2.0",
"react-dom": "^19.2.0"
}
}
Vue (package.json):
{
"dependencies": {
"vue": "^3.4.0"
}
}
关键差异:
react(核心库)+ react-dom(DOM 渲染器)React (main.jsx):
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
)
Vue (main.js):
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
对比:
render()StrictMode 提供开发时检查JSX = JavaScript + XML,允许在 JS 中直接写 HTML 标签。
示例:
function App() {
const name = "vue";
return (
<h1 className="title">Hello {name}!</h1>
)
}
| 特性 | React JSX | Vue 模板 |
|---|---|---|
| 类名 | className | class |
| 插值 | {name} | {{ name }} |
| 事件 | onClick={handler} | @click="handler" |
| 条件 | {condition && <div />} | v-if="condition" |
| 列表 | {items.map(i => <li />)} | v-for="i in items" |
JSX 代码:
const element = <h2>标题</h2>
编译后等价于:
const element2 = React.createElement('h2', null, '标题')
为什么使用 JSX?
// 函数就是组件
function App() {
return <h1>Hello React!</h1>
}
export default App
关键点:
function Header() {
return <header><h1>首页</h1></header>
}
function Articles() {
return <div>文章列表</div>
}
function App() {
return (
<>
<Header />
<Articles />
</>
)
}
Fragment (<>):不会创建额外 DOM 节点,类似 Vue 的 <template>
// 父组件
function App() {
return <UserProfile name="张三" />
}
// 子组件
function UserProfile({ name }) {
return <h1>欢迎,{name}!</h1>
}
对比 Vue:
<template>
<UserProfile :name="'张三'" />
</template>
<script setup>
const props = defineProps({ name: String })
</script>
import { useState } from 'react';
function App() {
const [name, setName] = useState("vue");
return <h1>Hello {name}!</h1>
}
解析:
useState 返回数组:[状态值,更新函数]"vue" 是初始值setName() 会触发重新渲染function App() {
const [name, setName] = useState("vue");
const [todos, setTodos] = useState([
{ id: 1, title: "学习 react" },
{ id: 2, title: "学习 node" },
]);
const [isLoggedIn, setIsLoggedIn] = useState(false);
return (
<>
<h1>Hello {name}!</h1>
{isLoggedIn ? <div>已登录</div> : <div>未登录</div>}
</>
)
}
// 错误:直接修改
todos.push(newTodo);
setTodos(todos);
// 正确:创建新数组
setTodos([...todos, newTodo]);
// 更新对象
setUser({ ...user, age: 26 });
为什么?
对比 Vue:
<script setup>
const todos = ref([])
// Vue 支持直接修改
todos.value.push(newTodo)
</script>
Vue 使用 Proxy 自动追踪变化,React 要求不可变更新。
function App() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
};
return <button onClick={handleClick}>+1</button>
}
关键点:
onClick(不是 onclick)onClick={handleClick}onClick={handleClick()} function App() {
const handleDelete = (id) => {
console.log('删除:', id);
};
return (
<ul>
{todos.map(todo => (
<li key={todo.id} onClick={() => handleDelete(todo.id)}>
{todo.title}
</li>
))}
</ul>
)
}
使用箭头函数传参,简单直观。
| 特性 | React | Vue |
|---|---|---|
| 语法 | onClick={handler} | @click="handler" |
| 阻止默认行为 | e.preventDefault() | .prevent 修饰器 |
| 事件对象 | 自动传递 | $event |
{isLoggedIn ? <div>已登录</div> : <div>未登录</div>}
{isLoggedIn && <div>已登录</div>}
React:
{count > 0 ? <p>{count}</p> : <p>无数据</p>}
Vue:
<p v-if="count > 0">{{ count }}</p>
<p v-else>无数据</p>
设计哲学:
function App() {
const todos = [
{ id: 1, title: "学习 react" },
{ id: 2, title: "学习 node" },
];
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.title}
</li>
))}
</ul>
)
}
// 正确:使用唯一 ID
<li key={todo.id}>
// 错误:使用索引
<li key={index}>
为什么需要 key?
React:
{todos.map(todo => <li key={todo.id}>{todo.title}</li>)}
Vue:
<li v-for="todo in todos" :key="todo.id">
{{ todo.title }}
</li>
import { useState } from 'react';
import './App.css';
function App() {
// 状态管理
const [name, setName] = useState("vue");
const [todos, setTodos] = useState([
{ id: 1, title: "学习 react", done: false },
{ id: 2, title: "学习 node", done: false },
{ id: 3, title: "学习 js", done: false },
]);
const [isLoggedIn, setIsLoggedIn] = useState(false);
// 事件处理
const toggleLogin = () => {
setIsLoggedIn(!isLoggedIn);
}
// JSX 元素
const element = <h2>JSX 是 React 的语法扩展</h2>
return (
<>
{element}
<h1>Hello <span className="title">{name}!</span></h1>
{/* 条件渲染 + 列表渲染 */}
{todos.length > 0 ? (
<ul>
{todos.map((todo) => (
<li key={todo.id}>
{todo.title}
</li>
))}
</ul>
) : (<div>暂无待办事项</div>)}
{/* 条件渲染 */}
{isLoggedIn ? <div>已登录</div> : <div>未登录</div>}
{/* 事件绑定 */}
<button onClick={toggleLogin}>
{isLoggedIn ? "退出登录" : "登录"}
</button>
</>
)
}
export default App
代码要点:
useState 管理三个状态map 方法实现列表渲染<>) 包裹多个元素| 方面 | React | Vue |
|---|---|---|
| 定位 | 库 (Library) | 框架 (Framework) |
| 模板 | JSX (JavaScript) | 模板语法 (HTML-like) |
| 状态更新 | 不可变 | 可变 |
| 学习曲线 | 较陡峭 | 较平缓 |
| 灵活性 | 高 | 中等 |
React:
import { useState } from 'react';
function App() {
const [count, setCount] = useState(0);
return (
<div>
<p>计数:{count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
)
}
Vue:
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<div>
<p>计数:{{ count }}</p>
<button @click="count++">+1</button>
</div>
</template>
{} 插值,不是 {{ }}className,不是 classonClick,不是 @clickkey,使用唯一 IDv-if// 错误
count = count + 1;
// 正确
setCount(count + 1);
// 错误
{items.map(item => <div>{item.name}</div>)}
// 正确
{items.map(item => <div key={item.id}>{item.name}</div>)}
// 错误
<div class="container">
// 正确
<div className="container">
// 错误
<button onClick={handleClick()}>
// 正确
<button onClick={handleClick}>
第 1 周:基础
第 2 周:进阶
第 3 周:生态
从 Vue 到 React,需要转变:
选 React 如果:
选 Vue 如果:
React 核心要点:
最后的话:
React 和 Vue 都是优秀框架,没有绝对好坏。理解差异,选择适合的,持续学习才是关键。
资源推荐:
祝你学习顺利!