对于刚完成 Vue 项目框架学习的前端新人而言,从 Vue 的选项式 API、响应式系统和组件模型转向 React 时,往往会面临语法体系、思维模式的切换挑战。本文基于一个使用 Vite 构建的 React 项目,结合 Vue 开发者的认知习惯,全面介绍 React 应用的基本架构、核心概念和最佳实践,帮助读者快速搭建 React 项目的知识框架,实现从 Vue 到 React 的平滑过渡。
🚀 一、 项目初始化
使用 Vite 创建 React 项目
在现代前端开发中,我们使用 Vite 作为构建工具来快速启动 React 项目:
npm init vite
为什么选择 Vite?
- 极致的冷启动速度:Vite 采用 ESM(ES Modules)模块化方案,无需打包即可启动开发服务器
- 现代化的工具链:原生支持 TypeScript、JSX、CSS 预处理器等
- 快速的热更新:基于浏览器原生 ESM,HMR 速度飞快
项目生命周期
一个完整的项目开发流程通常包括以下循环阶段:
-
dev:开发阶段,使用
npm run dev启动开发服务器
-
test:测试阶段,进行单元测试和集成测试
-
production:生产环境,打包部署到线上
我们可以发现,在 App.jsx 里面打印 count ,如图:
会有两个数字出现
这是因为在 main.jsx中,使用 StrictMode
核心原因是 StrictMode 会故意让某些函数 / 方法执行两次,这是 React 的设计行为,目的是帮你发现代码中的潜在问题,而且这个行为只在开发环境(development)中存在,生产环境(production)不会有。
哪些情况会被执行两次?
在 StrictMode 下,React 会对以下操作进行重复调用(通常是两次):
- 函数组件的主体代码(比如组件内部的
console.log(count)); useState、useMemo、useCallback等 Hook 的初始化函数;- 类组件的
constructor、render、shouldComponentUpdate等生命周期方法; - 类组件中定义的纯函数(比如事件处理函数) 。
📦二、 核心依赖解析
依赖类型
项目依赖分为两类:
1. 开发依赖(devDependencies)
仅在开发阶段使用,不会打包到生产环境:
npm i -D vite stylus
主要包括:
- vite:构建工具和开发服务器
- stylus:CSS 预处理器
- eslint:代码质量检查工具
- @vitejs/plugin-react:React 插件
当你用 -D 安装包时,npm 会做两件事:
- 把包下载到项目的
node_modules文件夹中(和普通安装一样)。 - 将包名和版本号记录到
package.json的devDependencies字段中,而非dependencies。
这样做的好处是:
- 区分依赖的用途,让项目的依赖结构更清晰。
- 当其他人协作开发或部署项目时,执行
npm install --production(生产环境安装),只会安装dependencies中的包,跳过devDependencies,减少生产环境的包体积,提升部署效率。
2. 项目依赖(dependencies)
会被打包到生产环境,运行时必需:
这些是 项目依赖(dependencies) ,也叫生产依赖,会被打包到生产环境中,是应用运行的核心库!
3. 开发依赖(devDependencies)
这些是 开发依赖(devDependencies) ,只在开发阶段使用,不会被打包到生产环境中。
React 生态核心库
1. React vs React-DOM
React 的架构采用分层设计:
- react:核心库,负责组件逻辑、状态管理、生命周期等
- react-dom:DOM 渲染层,负责将 React 组件渲染为浏览器 DOM
💡 类比理解:Vue.js = React(核心) + React-DOM(渲染层)
2. 关键特性
- 响应式数据绑定:数据变化自动更新视图
- 组件化开发:可复用的独立组件
- 虚拟 DOM:高效的 DOM 更新机制
- 单向数据流:可预测的状态管理
🏗️三、 项目架构
目录结构
react-demo/
├── node_modules/ # 依赖包
├── public/ # 静态资源
├── src/ # 源代码
│ ├── assets/ # 静态资源(图片、字体等)
│ ├── pages/ # 页面级组件
│ │ ├── Home.jsx # 首页
│ │ └── About.jsx # 关于页
│ ├── router/ # 路由配置
│ │ └── index.jsx # 路由主文件
│ ├── App.jsx # 根组件
│ ├── App.css # 根组件样式
│ ├── main.jsx # 应用入口
│ ├── index.css # 全局样式
│ └── index.styl # Stylus 样式
├── index.html # HTML 模板
├── package.json # 项目配置
├── vite.config.js # Vite 配置
└── README.md # 项目说明
入口文件:main.jsx
应用的启动文件,负责将 React 组件挂载到 DOM:
import { createRoot } from 'react-dom/client'
import './index.styl'
import App from './App.jsx'
createRoot(document.getElementById('root')).render(
<App />
)
核心流程:
-
使用
createRoot创建 React 根节点 -
选择 DOM 挂载点(
#root) -
渲染根组件
<App />
2️⃣ API 设计差异
| 特性 | React | Vue |
|---|---|---|
| 创建方式 | createRoot(容器).render(组件) | createApp(组件).mount(容器) |
| 链式调用 | 先创建根再渲染 | 先创建应用再挂载 |
| 调用顺序 | 容器 → 组件 | 组件 → 容器 |
| 返回值 | Root 对象 | App 实例 |
3️⃣ 核心理念差异
🛣️四、 React 路由配置
安装路由库
npm i react-router-dom
路由类型选择
React Router 提供两种路由模式:
1. BrowserRouter(推荐)
import { BrowserRouter as Router } from 'react-router-dom'
-
使用 HTML5 History API
-
URL 形式:
/about、/home -
更加美观和现代化
-
需要服务器配置支持
2. HashRouter
import { HashRouter as Router } from 'react-router-dom'
-
使用 URL hash(
#) -
URL 形式:
/#/about、/#/home -
无需服务器配置
-
兼容老旧浏览器
根组件配置:App.jsx
import {
BrowserRouter as Router,
Link
} from 'react-router-dom'
import './App.css'
import AppRoutes from './router/index'
function App() {
return (
<Router>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
</nav>
<AppRoutes />
</Router>
)
}
export default App
关键点:
-
使用
<Link>替代<a>标签,目的是实现无刷新的页面跳转(客户端路由)原生
<a href="/xxx">标签的行为是:- 点击后会触发浏览器的整页刷新,重新请求服务器获取新页面的 HTML、CSS、JS 等资源。
- 这会导致页面闪烁、加载耗时,破坏单页应用(SPA)“无刷新” 的核心特性。
而 React Router 提供的
<Link>组件,本质是拦截了点击事件,通过 JavaScript 动态修改浏览器的 URL 和页面内容,不会发起新的网络请求,实现客户端路由的无刷新跳转。 -
<Router>组件接管整个应用的路由控制 -
导航栏和路由视图分离
路由配置文件:router/index.jsx
import {
Routes, // 路由容器
Route, // 单个路由
} from 'react-router-dom'
import Home from '../pages/Home'
import About from '../pages/About'
export default function RouterConfig() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
)
}
组件说明:
-
<Routes>:路由总管,包裹所有路由规则 -
<Route>:定义单个路由映射-
path:URL 路径 -
element:对应的组件
-
🔥5、页面组件
About 页简单展示:
const About = () => {
return (
<div>
<h1>About</h1>
</div>
)
}
// 模块化输出 esm cjs commonjs
export default About
👉Home 页着重展示:
import {
// use 开头 函数 hooks 函数
useState, // 响应式状态管理
useEffect // 副作用管理 vue中 onMounted 挂载后
} from 'react';
const Home = () => {
const [repos, setRepos] = useState([]);
// render 是第一位的
console.log('组件初始化');
useEffect(() => {
// home 组件可以看到了,已经显示
console.log('挂载后')
// 发送api 请求,不会和组件渲染去争抢(单线程)
fetch('https://api.github.com/users/xxx/repos')
.then(res => res.json())
.then(data => {
// console.log(data);
setRepos(data);
})
}, [])
return (
<div>
<h1>Home</h1>
{
repos.length ? (
<ul>
{
repos.map(repo => (
<li key={repo.id}>
<a href={repo.html_url} target='_blank rel="noopener noreferrer"'>
{repo.name}
</a>
</li>
))
}
</ul>
) : (
<p>没有数据</p>
)
}
</div>
)
}
// 模块化输出 esm cjs commonjs
export default Home
一、useState:让函数组件拥有响应式状态
1. 什么是 useState?
useState 是 React 提供的状态钩子,用于在函数组件中定义响应式状态。所谓 “响应式”,就是当状态发生变化时,组件会自动重新渲染,更新页面上的内容。
2. 代码中的用法拆解
// 定义状态 repos,以及修改状态的方法 setRepos,初始值为空数组 []
const [repos, setRepos] = useState([]);
这行代码可以拆成三部分理解:
useState([]):调用useState并传入初始值(这里是空数组[]),它会返回一个数组。repos:当前的状态值,初始是[],后续可以通过setRepos修改它。setRepos:修改状态的更新函数,调用它可以改变repos的值,并且触发组件重新渲染。
3. 在代码中,useState 的作用流程
- 组件初始化时,
repos被初始化为空数组[],所以页面上会先显示<p>没有数据</p>。 - 当
fetch请求获取到 GitHub 仓库数据后,调用setRepos(data),将repos的值更新为接口返回的数组。 - 状态更新后,组件会重新渲染,此时
repos.length为真,页面会渲染仓库列表的<ul>和<li>。
4. useState 的核心特点
-
状态是隔离的:每个组件实例的
useState状态都是独立的,不会互相影响。 -
更新函数是异步的(批量更新) :
setRepos不会立即改变repos的值,React 会批量处理状态更新,再统一触发渲染。 -
可以定义多个状态:一个组件中可以多次调用
useState,管理不同的状态:const [count, setCount] = useState(0); const [name, setName] = useState('张三');
二、useEffect:处理组件的副作用
1. 什么是 “副作用”?
在 React 中,副作用指的是那些不直接参与组件渲染的操作,常见的有:
- 网络请求(如
fetch调用); - 操作 DOM(如修改元素样式、添加事件监听);
- 定时器 / 计数器(
setInterval/setTimeout); - 订阅 / 取消订阅(如 WebSocket 连接)。
useEffect 就是专门用来处理这些副作用的钩子,它可以模拟类组件的生命周期(如 componentDidMount、componentDidUpdate、componentWillUnmount)。
🔄六、 开发工作流
Vite 的优势
-
智能编译:
- 自动将 Stylus 编译为 CSS
- 支持 JSX 语法转换
- TypeScript 开箱即用
-
快速热更新:
- 组件级别的热更新
- 保留应用状态
- 毫秒级响应
-
按需加载:
- 开发时按需编译
- 生产构建自动优化
🎯七、 最佳实践
1. 组件化思维
- 将页面拆分为独立、可复用的组件
- 遵循单一职责原则
- 使用 JSX 编写组件模板
2. 路由管理
-
集中管理路由配置
pages目录 -
使用
Link组件进行导航
3. 样式管理
- 全局样式:index.css / index.styl
- 组件样式:与组件同名的 CSS 文件
- 支持 CSS 预处理器(Stylus、Sass 等)
4. 代码质量
- 配置 ESLint 进行代码检查
- 使用 TypeScript 增强类型安全
- 遵循 React Hooks 最佳实践
📝 总结
本文介绍了基于 Vite 的 React 项目基本框架:
核心要点
-
构建工具:Vite 提供极速的开发体验和现代化的构建能力
-
React 生态:
-
react:核心逻辑 -
react-dom:DOM 渲染 -
react-router-dom:路由管理
-
-
项目结构:清晰的目录划分,组件化开发
-
路由系统:使用 React Router 实现单页应用导航