目录
一、React介绍
1.1 什么是React
1.2 React 的特点
1.3 React VS Vue VS Angular
1. 基本概述
2. 语法和核心概念对比
2.1 组件语法
2.1.1 React 组件
2.1.2 Vue 组件
2.1.3 Angular 组件
2.2 数据绑定
2.2.1 React(单向数据流)
2.2.2 Vue(双向数据绑定)
2.2.3 Angular(双向数据绑定)
2.3 事件绑定
3.性能对比
4.生态系统
5.开发体验
6.适用场景
7. 总结
二、环境搭建
1. 安装node.js
2. 安装 pnpm
3. 使用 Vite 创建 React 项目
4. 运行开发服务器
5. 目录结构
6. 构建项目
三、JSX 语法
1. JSX 语法规则(表达式、属性、子元素)
1. JSX 表达式
2. JSX 属性(Props)
字符串属性
JavaScript 表达式
传递对象
传递事件处理函数
3. JSX 子元素
单个子元素
多个子元素
组件嵌套
使用数组渲染列表
4 特殊情况
条件渲染
2. JSX 与 JavaScript 的区别
1️⃣ JSX 是 JavaScript 的语法扩展
2️⃣ JSX 需要使用 className 而不是 class
3️⃣ JSX 中的属性需要使用大括号 {} 传递变量
4️⃣ JSX 需要使用 camelCase 语法定义 HTML 属性
5️⃣ JSX 需要有一个唯一的父级元素
6️⃣ JSX 可以直接嵌入表达式,但不能嵌入语句
7️⃣ JSX 不能使用 if 语句,但可以使用三元运算符
8️⃣ JSX 中的 style 需要使用对象
9️⃣ JSX 需要手动添加 key 属性给列表渲染
✅ 总结:JSX vs JavaScript
四、组件基础
1. React 组件的概念
1.1 组件的两种类型
✅ 函数组件(Function Component)
✅ 类组件(Class Component)
1.2 组件的核心特性
✅ 1. 组件可以复用
✅ 2. 组件可以接收 props
✅ 3. 组件可以有 state
✅ 4. 组件生命周期(类组件)
✅ 5. 组件可以嵌套
1.3 组件的最佳实践
✅ 1. 组件应该小而精,保持单一职责
✅ 2. 组件应该是可复用的
✅ 3. 组件状态应该尽可能向上提升
✅ 4. 组件避免不必要的渲染
总结
2. 组件的 props 和 children
2.1 组件的 props 和 children
2.2 props (属性)
2.3 children (子元素)
2.4 props vs children
3. 组件的 defaultProps 和 propTypes
组件的 defaultProps 和 propTypes
✅ defaultProps:设置默认 props
作用
使用方式
使用示例
适用场景
✅ propTypes:进行 props 类型检查
作用
使用方式
适用场景
✅ defaultProps 和 propTypes 配合使用
defaultProps 和 propTypes 的区别
注意事项
结论
React 是一个用于构建用户界面的JS库。
框架 |
React |
Vue |
Angular |
创建时间 |
2013 (Facebook) |
2014 (尤雨溪) |
2010 (Google) |
框架类型 |
仅 UI 库 (需要结合其他工具) |
渐进式框架 |
完整前端框架 |
语言 |
JavaScript / TypeScript |
JavaScript / TypeScript |
TypeScript |
数据绑定 |
单向数据流 |
双向数据绑定 + 单向数据流 |
双向数据绑定 |
状态管理 |
useState、useReducer、Redux、Zustand |
Vuex、Pinia |
RxJS、NgRx |
路由管理 |
react-router |
vue-router |
Angular Router |
官方维护 |
Meta (Facebook) |
独立开发者 (尤雨溪) |
|
适合项目 |
组件化、交互丰富的 UI |
轻量级、灵活应用 |
企业级、复杂应用 |
React 使用 JSX,Vue 和 Angular 使用 模板语法。
function App() {
return Hello React
;
}
Hello Vue
@Component({
selector: 'app-root',
template: 'Hello Angular
'
})
export class AppComponent {}
对比项 |
React |
Vue |
Angular |
数据流 |
单向数据流 (props + state) |
双向绑定 (v-model) + 单向流 |
双向绑定 ([(ngModel)]) |
状态管理 |
useState、useReducer |
ref()、reactive() |
RxJS、NgRx |
function App() {
const [count, setCount] = useState(0);
return ;
}
export class AppComponent { message = "Hello Angular"; }
对比项 |
React |
Vue |
Angular |
事件绑定 |
onClick={() => fn()} |
@click="fn" |
(click)="fn()" |
对比项 |
React |
Vue |
Angular |
虚拟DOM |
diff 算法 |
优化更高效 |
真实DOM 变更较慢 |
首屏加载 |
快 |
更快 |
慢(需要完整引导) |
文件大小 |
约 42 KB |
约 35 KB |
约 500 KB |
渲染方式 |
CSR 、SSR 、SSG |
CSR 、SSR 、SSG |
CSR 、SSR |
Vue 和 React 都使用虚拟 DOM ,但 Vue 3 采用的 Proxy 进行数据劫持,比 React useState 方式更高效。Angular 由于使用真实 DOM,性能相对比较慢。
React 生态最广,Vue 灵活,Angular 适合大型项目。
对比项 |
React |
Vue |
Angular |
组件库 |
Ant Design、MUI、Chakra UI |
Element Plus、Vuetify |
Angular Material |
状态管理 |
Redux、Zustand |
Vuex、Pinia |
RxJS、NgRx |
移动端 |
React Native |
Quasar |
Ionic |
服务端渲染 |
Next.js |
Nuxt.js |
Angular Universal |
Vue 上手最快,React 自由度高,Angular 规则最严格。
对比项 |
React |
Vue |
Angular |
上手难度 |
⭐⭐⭐(中等) |
⭐⭐(最简单) |
⭐⭐⭐⭐(最难) |
开发方式 |
JSX 代码更自由 |
模板更直观 |
复杂 |
文档 |
官方文档丰富 |
文档清晰 |
文档较难读 |
社区支持 |
超大 |
大 |
企业支持强 |
场景 |
React |
Vue |
Angular |
个人项目 |
✅ 适合 |
✅ 最佳选择 |
❌ 过于复杂 |
企业级应用 |
✅ 可用 |
✅ 适用 |
✅ 最适合 |
移动端 |
✅ React Native |
✅ Quasar |
✅ Ionic |
SEO(SSR) |
✅ Next.js |
✅ Nuxt.js |
✅ Angular Universal |
后台管理 |
✅ Ant Design |
✅ Element Plus |
✅ Angular Material |
大规模团队开发 |
✅ 可维护 |
✅ 灵活 |
✅ 最佳选择 |
选择建议:
对比项 |
React |
Vue |
Angular |
学习成本 |
⭐⭐⭐ |
⭐⭐ |
⭐⭐⭐⭐ |
灵活性 |
⭐⭐⭐⭐ |
⭐⭐⭐ |
⭐ |
性能优化 |
⭐⭐⭐⭐ |
⭐⭐⭐⭐⭐ |
⭐⭐⭐ |
企业级支持 |
⭐⭐⭐ |
⭐⭐ |
⭐⭐⭐⭐⭐ |
Vue → 最简单,适合个人开发者、新手学习
React → 生态最丰富,适合大型项目
Angular → 结构严谨,适合企业级开发
如果已经安装了 node,建议使用 nvm 来管理多个 node 版本。
node: Node.js — 在任何地方运行 JavaScript
nvm: nvm文档手册 - nvm是一个nodejs版本管理工具 - nvm中文网
pnpm 是一个高效的包管理工具,比 npm 和 yarn 更快。全局安装 pnpm
npm install -g pnpm
Vite 是一个快速的构建工具,推荐用于 React 开发。使用以下命令创建一个 React + TypeScript 项目:
pnpm create vite@latest my-react-app --template react-ts
如果想创建 React + JavaScript 项目:
pnpm create vite@latest my-react-app --template react
在项目目录中执行:
pnpm dev
默认情况下,Vite 会在 http://localhost:5173 启动开发服务器。
项目创建后,基本结构如下:
my-react-app
│── public/ # 静态资源
│── src/ # 源代码
│ ├── assets/ # 静态资源(图片、CSS等)
│ ├── components/ # 组件
│ ├── App.tsx # 入口组件
│ ├── main.tsx # 入口文件
│── index.html # HTML 入口
│── package.json # 依赖管理
│── vite.config.ts # Vite 配置文件
打包生产环境代码:
pnpm build
打包后,文件会生成在 dist/ 目录中。
JXS (JavaScript XML) 是 React 推荐的语法扩展,它允许你在 JavaScript 代码中编写类似 HTML 的代码。JSX 本质上是 React.createElement() 的语法糖,最终会被编译为 JavaScript 代码。
在JSX 中使用 JavaScript 表达式
在JSX 语法中,可以使用 {} 将JavaScript 表达式嵌入到 JSX 代码中:
const name = "React";
const element = Hello, {name}!
;
支持的表达式:
不支持的表达式:
可以使用引号 "" 直接赋值:
const element =
;
使用 {} 传递动态值:
const isActive = true;
const element = ;
const style = { color: "blue", fontSize: "20px" };
const element = This is styled text.
;
const handleClick = () => alert("Clicked!");
const button = ;
❌ 不允许的写法(不要用 class 作为属性):
const element = Hello; // ❌ 错误
✅ React 需要用 className 代替 class:
const element = Hello; // ✅ 正确
const element = Hello, World!
;
多个 JSX 元素必须包裹在一个父元素中(如
或 <>)。
const element = (
Title
Content
);
或使用 React Fragment (<> ... ):
const element = (
<>
Title
Content
>
);
JSX 允许组件作为子元素:
function Welcome() {
return Welcome to React!
;
}
const App = () => (
);
const items = ["Apple", "Banana", "Cherry"];
const list = (
{items.map((item, index) => (
- {item}
))}
);
✅ 使用三元运算符:
const isLoggedIn = true;
const element = {isLoggedIn ? "Welcome back!" : "Please log in."}
;
✅ 使用 && 逻辑运算:
const isAdmin = true;
const element = {isAdmin && "You have admin privileges."}
;
JSX(JavaScript XML)是 React 中的语法扩展,它看起来像 HTML,但本质上仍然是 JavaScript。JSX 代码最终会被 Babel 编译为纯 JavaScript 代码。下面是 JSX 和 JavaScript 的一些主要区别:
JSX 允许在 JavaScript 代码中编写类似 HTML 的代码,而 JavaScript 不能直接写 HTML。
✅ JSX 代码
const element = Hello, React!
;
❌ 纯 JavaScript 代码
const element = React.createElement("h1", null, "Hello, React!");
JSX 代码最终会被编译成纯 JavaScript,如上所示。
JSX 是 JavaScript 的扩展,而 class 是 JavaScript 的关键字,因此在 JSX 中必须使用 className 代替 class。
✅ JSX
const element = Hello;
❌ JavaScript(报错)
const element = Hello; // ❌ React 会报错
✅ JSX
const name = "React"; const element = Hello, {name}!
;
❌ JavaScript(不支持 JSX 语法)
const name = "React"; const element = React.createElement("h1", null, "Hello, " + name + "!");
在 JSX 中,onclick、onchange 这些 HTML 事件必须写成 camelCase 格式,如 onClick、onChange。
✅ JSX
const button = ;
❌ JavaScript
const button = React.createElement(
"button",
{ onclick: () => alert("Clicked!") }, // ❌ React 不支持小写的 `onclick`
"Click me"
);
在 JSX 中,所有 JSX 代码必须被一个唯一的父元素包裹,而 JavaScript 不需要。
✅ JSX
const element = (
Title
Content
);
或者使用 Fragment:
const element = (
<>
Title
Content
>
);
❌ JavaScript
const element = [
React.createElement("h1", null, "Title"),
React.createElement("p", null, "Content"),
]; // ❌ 需要包裹在一个 `div` 或 `Fragment` 里
在 JSX 中,你可以使用 JavaScript 表达式(如 变量、函数调用、三元运算符),但不能使用 JavaScript 语句(如 if、for)。
✅ JSX
const isLoggedIn = true;
const message = {isLoggedIn ? "Welcome back!" : "Please log in."}
;
❌ 错误写法
const message = if (isLoggedIn) { Welcome back!
}; // ❌ JSX 不支持 if 语句
✅ 正确的 JSX 语法
const message = isLoggedIn ? Welcome back!
: Please log in.
;
JavaScript 支持 if 语句,但 JSX 只能使用三元运算符 ? : 或 &&。
✅ JSX
const isAdmin = true;
const adminPanel = isAdmin ? Admin Panel
: null;
❌ JavaScript
let adminPanel;
if (isAdmin) {
adminPanel = React.createElement("p", null, "Admin Panel");
}
JSX 不支持直接写行内 CSS 字符串,必须使用 对象,且 CSS 需要使用 camelCase 语法。
✅ JSX
const style = { color: "blue", fontSize: "20px" };
const element = Styled Text
;
❌ JavaScript
const element = React.createElement("p", { style: "color: blue; font-size: 20px;" }, "Styled Text"); // ❌ 报错
在 JSX 中,React 要求使用 key 来唯一标识列表项,而 JavaScript 不需要。
✅ JSX
const items = ["Apple", "Banana", "Cherry"];
const list = (
{items.map((item, index) => (
- {item}
))}
);
❌ JavaScript
const items = ["Apple", "Banana", "Cherry"];
const list = React.createElement(
"ul",
null,
items.map((item, index) => React.createElement("li", { key: index }, item))
); // JavaScript 需要手动创建 `React.createElement`
对比项 |
JSX |
纯 JavaScript |
语法 |
类似 HTML |
纯 JavaScript |
HTML 结构 |
可以直接写 |
需要 React.createElement() |
属性名 |
使用 className、htmlFor |
class、for |
事件绑定 |
onClick={handleClick} |
onclick: handleClick |
条件渲染 |
isLogin ? "Welcome" : "Login" |
if (isLogin) {} |
CSS 样式 |
{ color: "red" } |
"color: red;" |
列表渲染 |
{items.map(item =>
|
React.createElement("ul", null, items.map(...)) |
JSX 是 React 的核心语法,它让 React 代码更易读,但本质上它仍然是 JavaScript,在运行前会被 Babel 编译为纯 JavaScript 代码!
React 组件(Component) 是 React 应用的 基本构建块,用于 封装 UI 逻辑,使界面可复用、模块化、易维护。
在 React 中,组件本质上是 JavaScript 函数(或类),它们返回 JSX(类似 HTML 的语法),然后 React 负责将其渲染到页面上。
React 组件主要分为 函数组件(Function Component) 和 类组件(Class Component)。
函数组件 是使用 JavaScript 的函数定义的,它接受 props 作为参数,并返回 JSX。
function Welcome(props) {
return Hello, {props.name}!
;
}
// 使用组件
类组件 继承自 React.Component,必须实现 render() 方法返回 JSX。
import React, { Component } from "react";
class Welcome extends Component {
render() {
return Hello, {this.props.name}!
;
}
}
// 使用组件
function Button(props) {
return ;
}
export default function App() {
return (
);
}
同一个 Button 组件,可以多次使用,并传入不同的 label。
props(属性) 用于组件间传递数据,类似 HTML 标签的 attributes。
function UserProfile(props) {
return User: {props.username}
;
}
// 使用
在类组件中:
class UserProfile extends React.Component {
render() {
return User: {this.props.username}
;
}
}
props 只读,不能修改!
state 用于存储组件的内部数据,可在组件内部修改。
在函数组件中(使用 useState):
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return ;
}
在类组件中:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
render() {
return ;
}
}
函数组件推荐使用 Hooks(如 useState),比类组件更简洁!
类组件有生命周期方法,如:
示例:
class Timer extends React.Component {
componentDidMount() {
console.log("组件已挂载");
}
componentWillUnmount() {
console.log("组件即将卸载");
}
render() {
return Timer Running...
;
}
}
在 函数组件 中,使用 useEffect 代替:
import { useEffect } from "react";
function Timer() {
useEffect(() => {
console.log("组件已挂载");
return () => {
console.log("组件即将卸载");
};
}, []);
return Timer Running...
;
}
父组件可以包含子组件:
function Header() {
return Welcome to React
;
}
function App() {
return (
This is a React app.
);
}
特性 |
函数组件 |
类组件 |
语法 |
function |
class |
props 传递 |
直接作为参数 |
this.props |
状态管理 |
useState() |
this.state |
生命周期 |
useEffect() |
componentDidMount() 等 |
推荐使用 |
✅(官方推荐) |
❌(React 16.8 之后不推荐) |
现在 React 开发主要使用 函数组件 + Hooks!
在 React 组件中,props 和 children 都是用于 数据传递 和 组件复用 的重要概念。
props 是 组件的输入参数,用于在 父组件向子组件 传递数据。
✅ props 的基本用法
父组件传递 props 给子组件
function UserCard(props) {
return Username: {props.name}
;
}
// 父组件使用
✅ props 不能修改(只读)
❌ 错误
function UserCard(props) {
props.name = "Jack"; // ❌ props 是只读的,不能修改!
return Username: {props.name}
;
}
✅ 正确
function App() {
const [username, setUsername] = useState("Tom");
return ;
}
✅ props 的默认值
有时候 props 可能为空,我们可以用 defaultProps 或 ES6 默认参数。
方法 1:ES6 默认参数
function UserCard({ name = "Guest" }) {
return Username: {name}
;
}
方法 2:defaultProps
UserCard.defaultProps = {
name: "Guest"
};
✅ props 结构化赋值
简化 props 的写法:
function UserCard({ name, age }) {
return {name} is {age} years old.
;
}
使用:
如果使用或了解过vue的话,children 更像是 solt 插槽。
children 代表 组件的内部内容,类似于 HTML 标签内的内容。
✅ children 的基本用法
function Wrapper(props) {
return {props.children};
}
function App() {
return (
Hello React
This is a React app.
);
}
Hello React
This is a React app.
✅ children 适用于哪些场景?
function Card({ children }) {
return {children};
}
Title
Content here...
function Border({ children }) {
return {children};
}
React App
function List({ children }) {
return {children}
;
}
Item 1
Item 2
✅ children 作为函数
有时候,我们希望 children 作为 函数 传递,以支持更灵活的渲染。
function RenderPropsExample({ children }) {
return {children("Hello from function!")};
}
{(message) => {message}
}
对比项 |
props |
children |
作用 |
组件的输入参数 |
组件的内部内容 |
传递方式 |
子内容 |
|
适用场景 |
组件配置(如 name, age, id ) |
组件插槽(如布局、嵌套内容) |
访问方式 |
props.propName |
props.children |
在 React 组件中,defaultProps 和 propTypes 用于管理 props 的默认值和类型检查,分别解决:
当父组件没有传递某个 prop 时,defaultProps 提供默认值,确保组件能正常运行。
import React from "react";
function Button({ label, color }) {
return ;
}
// 设置默认 props
Button.defaultProps = {
label: "默认按钮",
color: "blue",
};
export default Button;
// 没传 label,默认值为 "默认按钮"
// 传递了 label,不使用默认值
用于检查组件 props 的 类型是否正确,防止传递错误数据导致 bug。
import PropTypes from "prop-types";
function Button({ label, color }) {
return ;
}
// 设置默认 props
Button.defaultProps = {
label: "默认按钮",
color: "blue",
};
// 定义 props 类型检查
Button.propTypes = {
label: PropTypes.string, // label 必须是字符串
color: PropTypes.string, // color 必须是字符串
};
export default Button;
import PropTypes from "prop-types";
function Card({ title, content, showBorder }) {
return (
{title}
{content}
);
}
// 设置默认值
Card.defaultProps = {
title: "默认标题",
content: "这里是默认内容",
showBorder: true,
};
// 设置类型检查
Card.propTypes = {
title: PropTypes.string.isRequired, // 必须传递
content: PropTypes.string,
showBorder: PropTypes.bool,
};
export default Card;
对比项 |
defaultProps |
propTypes |
作用 |
设置默认值 |
进行类型检查 |
影响 |
影响组件 props 的默认值 |
不影响 props 运行 |
什么时候触发 |
当 props 为空时 |
传递的 props 类型错误时 |
是否会影响生产环境 |
✅ 会生效 |
❌ 仅在开发环境生效 |
是否必须 |
❌ 不是必须的 |
❌ 不是必须的 |
function Button({ label = "默认按钮", color = "blue" }) {
return ;
}
✅ defaultProps 解决的是 props 为空时的默认值,适合给非必填 props 赋值。
✅ propTypes 解决的是 props 类型检查,适合约束 props 类型,避免错误传参。
✅ 如果项目使用 TypeScript,可以直接使用 interface 代替 propTypes。