嘿,各位前端小伙伴!如果你是一个熟练使用 Vue 的开发者,面对 React 19 的新特性和“一切皆函数”的逻辑感到有些迷茫,那这篇文章就是为你准备的。
我们要聊的是前端架构。我们将结合最新的 React 19.2.0,对比 Vue 的开发习惯,手把手带你搭起一个高性能的项目。
一、 选对“地基”:Vite 与环境配置
1.1 开发流程:Vite 是共同的语言
在 Vue 和 React 中,Vite 都扮演着“脚手架”的角色。
- 命令:
npm init vite - 周期:
dev(开发) ->test(测试) ->production(生产上线)。这是一个循环迭代的过程。
1.2 依赖管理:谁该留在服务器?
在项目根目录的 package.json 中,你会看到两类依赖。
| 依赖类型 | React 示例 | Vue 示例 | 作用 |
|---|---|---|---|
| devDependencies | vite, stylus | vite, sass | 仅开发环境使用,打包后剔除 |
| dependencies | react, react-router-dom | vue, vue-router | 生产环境必须运行的代码 |
关键讲解 1:npm i -D stylus
这里的 -D (或者 --save-dev) 是新手最容易忽略的。Stylus 是一种 CSS 预处理器,它只在开发阶段由 Vite 编译成 CSS。一旦项目打包上线,浏览器只认识 CSS,不再需要 Stylus 工具本身。所以我们把它放在 devDependencies 里,减小上线包的体积。
二、 核心对比:Vue 3.5 vs React 19
很多新手好奇:为什么 React 要引入两个核心包?
- React (Core): 负责逻辑、Diff 算法、Hooks。
- React-DOM: 负责把逻辑变成真正的 HTML 元素。
对比:
- Vue:
import { createApp } from 'vue'—— 一个包搞定所有,高度集成。 - React:
react是大脑,react-dom是手脚。这种解耦让 React 能够通过更换“手脚”去开发手机 App (React Native) 或 3D 场景 (React Three Fiber)。
三、 入口文件:HTML 与挂载点
3.1 极简的 index.html
React 的 HTML 极其干净,这和 Vue 几乎一致:
HTML
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
3.2 渲染入口:main.jsx vs main.js
这是程序启动的第一站。
React 代码:
import { createRoot } from 'react-dom/client'
import './index.styl' // 全局样式
import App from './App.jsx' // 引入组件
// 将 APP 组件挂载到 root 元素上 渲染render
createRoot(document.getElementById('root')).render(
<App /> // 函数组件的名字 类html 标签 自定义组件
)
为什么是 .jsx文件?因为要调用这个组件用法
Vue 对比代码:
JavaScript
import { createApp } from 'vue'
import App from './App.vue'
// 引入路由模块
import router from './router'
createApp(App).use(router).mount('#app')
可以看到
vue的router在这里引入使用
关键讲解 2: 严格模式会执行两次
在开发环境下,如果你开启了 ,React 会故意让组件渲染两次。这不是 Bug! 它是为了帮你测试组件是否“纯净”。如果你的代码在渲染两次时出现了奇怪的副作用(比如数据翻倍),说明你的逻辑写错位置了。
四、 路由:项目的“导航员”
4.1 引入路由
React 使用 react-router-dom。
App.jsx 代码:
JavaScript
import { BrowserRouter as Router, Link } from 'react-router-dom'
// 与HashRouter对比,BrowserRouter更加现代与后端路由格式一样,但是低端浏览器不兼容
import AppRouters from './router'
function App() {
return (
<Router> {/* 路由接管一切,相当于 Vue 的整个路由环境 */}
<nav>
<Link to="/">首页</Link> {/* 代替 a 标签,内部消化,不刷新页面 */}
<Link to="/about">关于</Link>
</nav>
<AppRouters />//本质就是routes,作为"调度员"指定此刻应该显示哪个“页面级组件”
</Router>
)
}
关键讲解 3:
Link组件与as Router
as Router: 这是 JS 的起别名语法。BrowserRouter名字太长,起个别名Router更好记。Link代替a: 在单页应用中,如果你用<a href="/">,点击时页面会刷新,导致状态丢失。Link组件会拦截点击,只改变 URL 并更新组件,实现“秒开”体验。对应 Vue 的<router-link>。- 当用户点击一个
<Link>,React Router 会根据to的路径匹配<AppRouters />中定义的<Route>,并渲染对应的组件。
vue之不同:
由于vue早在main.js中就已经引入并use(router)所以在相应的App.vue直接使用<router-link>与<router-view>即可
4.2 路由配置:router/index.js
react:
import { Routes, Route } from 'react-router-dom';
import Home from '../pages/Home';
export default function AppRouters() {
return (
<Routes> {/* 前端路由总管,对应 Vue 的 <router-view> 的逻辑层 */}
<Route path="/" element={<Home />} /> {/* 具体路由实例 */}
</Routes>
)
}
依旧是组件化思想,返回一个打包好的路由组件。
vue:
import {
createRouter,// 前端路由实例
createWebHashHistory // 路由模式
} from 'vue-router'
import Home from '../views/Home.vue';
const routes = [
{
path:'/',
name:'Home',
component:Home
}
];
// 实例化 负责前端路由
const router = createRouter({
// 访问历史 hash 路由 #/about
history:createWebHashHistory(),
// 路由配置数组
routes
})
export default router;
五、 核心:Home 页面与 Hooks 深度解析
这是 React 19 最灵魂的部分。我们用获取 GitHub 仓库列表为例。
5.1 组件代码对比
React 版本 (Home.jsx):
JavaScript
import { useState, useEffect } from 'react';
const Home = () => {
// 关键点 A:useState 响应式状态
const [repos, setRepos] = useState([]);
console.log('组件初始化'); // 每次渲染都会执行
// 关键点 B:useEffect 副作用管理
useEffect(() => {
fetch('https://api.github.com/users/shunwuyu/repos')
.then(res => res.json())
.then(data => {
setRepos(data); // 关键点 C:修改状态
});
}, []); // 关键点 D:空数组依赖
return (
<div>
{repos.length ? (
<ul>
{repos.map(repo => (
<li key={repo.id}>{repo.name}</li>
))}
</ul>
) : (
<p>暂无仓库</p>
)}
</div>
)
}
Vue 版本 (Home.vue):
代码段
<script setup>
import { ref, onMounted } from 'vue';
const repos = ref([]); // 对应 useState
console.log('组件初始化');
onMounted(() => { // 对应 useEffect
fetch('...')
.then(res => res.json())
.then(data => {
repos.value = data; // 对应 setRepos
});
});
</script>
<template>
<ul v-if="repos.length"> <li v-for="repo in repos" :key="repo.id">{{ repo.name }}</li>
</ul>
<p v-else>暂无仓库</p>
</template>
5.2 知识点拆解
关键讲解 4:useState (响应式状态管理)
- Vue: 你定义
ref([]),修改时用repos.value = ...。Vue 偷偷在背后帮你追踪变化。 - React: 使用
const [data, setData] = useState(初始值)。React 规定:你不可以直接修改 data。必须调用setData,React 才会知道“哦!数据变了,我要重新画一遍页面”。这叫“显式更新”。
关键讲解 5:useEffect (副作用与挂载)
-
为什么叫副作用? 渲染 HTML 是主业,而联网取数据、定时器、操作 DOM 都是“副业”。应该在渲染完成之后再做
-
关键点
[](依赖项):- 如果不传这个数组,组件只要一更新(比如你打个字),
useEffect就会重新跑,会导致无限循环请求 API。 - 传入
[]:告诉 React:“这个动作只在组件 第一次挂载(onMounted) 时做一次,以后别管了。”
- 如果不传这个数组,组件只要一更新(比如你打个字),
关键讲解 6:渲染逻辑 (JSX vs Directives)
-
Vue 使用指令:
v-if控制显隐,v-for控制列表。 -
React 使用原汁原味的 JS:
- v-if: 变成
{ condition ? <Yes /> : <No /> }(三元运算符)。 - v-for: 变成
repos.map(...)。数组的map方法会把数据变成一堆 HTML 标签,React 就能直接渲染它们。
- v-if: 变成
关键讲解 7:key 的重要性
不管是 Vue 的 :key 还是 React 的 key,在循环列表中必须唯一。
- 原理: 当数据变了,React 会根据
key去对比:“哎,这个 ID 为 123 的列表项没变,我不重新画它了;那个 ID 为 456 的变了,我只更新它。”这大大提升了渲染速度。
六、 总结:从 Vue 迁移到 React 的心法
- 从“自动”到“手动”: Vue 帮你处理了依赖追踪,React 需要你手动通过
useState和useEffect的依赖数组来声明。 - 从“模板”到“函数”: Vue 是把逻辑写进模板(HTML 增强版),React 是把 HTML 写进逻辑(JSX)。
- 单向数据流: 在 React 中,数据永远是从上往下流动的。