React入门完全教程
什么是React?
React是由Facebook(现Meta)开发的一个用于构建用户界面的JavaScript库。它采用组件化思想,让你可以将UI拆分成独立、可复用的部分,从而高效地构建复杂的用户界面。
React的核心特点:
- 声明式:你只需描述UI应该是什么样子,React会自动处理DOM更新
- 组件化:将界面拆分为独立的组件,每个组件管理自己的状态
- 虚拟DOM:通过内存中的虚拟DOM树,最小化实际DOM操作,提升性能
- 单向数据流:数据自上而下流动,让代码更可预测、更易调试
环境搭建
方式一:使用Create React App(推荐新手)
npx create-react-app my-first-app
cd my-first-app
npm start
方式二:使用Vite(更快的构建工具)
npm create vite@latest my-react-app -- --template react
cd my-first-app
npm install
npm run dev
JSX语法基础
JSX是JavaScript的语法扩展,让你可以在JavaScript中编写类似HTML的代码。
// JSX基本语法
const element = <h1>Hello, React!</h1>;
// 在JSX中使用JavaScript表达式(用花括号包裹)
const name = "张三";
const greeting = <h1>你好,{name}!</h1>;
// JSX中的条件渲染
function Welcome({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? <h1>欢迎回来!</h1> : <h1>请先登录</h1>}
</div>
);
}
// JSX中的列表渲染
function TodoList({ items }) {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}
组件
函数组件(推荐)
// 最简单的函数组件
function Greeting() {
return <h1>你好,世界!</h1>;
}
// 带Props的组件
function UserCard({ name, age, avatar }) {
return (
<div className="user-card">
<img src={avatar} alt={name} />
<h2>{name}</h2>
<p>年龄:{age}</p>
</div>
);
}
// 使用组件
function App() {
return (
<div>
<UserCard name="张三" age={25} avatar="/avatar.jpg" />
<UserCard name="李四" age={30} avatar="/avatar2.jpg" />
</div>
);
}
类组件(了解即可)
import React, { Component } from 'react';
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<p>计数:{this.state.count}</p>
<button onClick={this.increment}>+1</button>
</div>
);
}
}
State(状态)
State是组件内部管理的数据,当state变化时,组件会自动重新渲染。
import { useState } from 'react';
function Counter() {
// useState返回[state值, 更新函数]
const [count, setCount] = useState(0);
return (
<div>
<p>你点击了 {count} 次</p>
<button onClick={() => setCount(count + 1)}>
点击我
</button>
</div>
);
}
// 复杂state管理
function TodoApp() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState('');
const addTodo = () => {
if (input.trim()) {
setTodos([...todos, { id: Date.now(), text: input, done: false }]);
setInput('');
}
};
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, done: !todo.done } : todo
));
};
return (
<div>
<input value={input} onChange={e => setInput(e.target.value)} />
<button onClick={addTodo}>添加</button>
<ul>
{todos.map(todo => (
<li
key={todo.id}
onClick={() => toggleTodo(todo.id)}
style={{ textDecoration: todo.done ? 'line-through' : 'none' }}
>
{todo.text}
</li>
))}
</ul>
</div>
);
}
Props(属性)
Props是组件接收的外部数据,类似于函数的参数。
// 父组件传递Props
function App() {
return (
<UserProfile
name="张三"
age={25}
skills={['React', 'TypeScript', 'Node.js']}
isVip={true}
/>
);
}
// 子组件接收Props
function UserProfile({ name, age, skills, isVip }) {
return (
<div className="profile">
<h2>{name} {isVip && '👑'}</h2>
<p>年龄:{age}</p>
<div className="skills">
{skills.map(skill => (
<span key={skill} className="tag">{skill}</span>
))}
</div>
</div>
);
}
常用Hooks
useEffect - 副作用处理
import { useState, useEffect } from 'react';
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// 组件挂载或userId变化时执行
setLoading(true);
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => {
setUser(data);
setLoading(false);
});
// 清理函数(组件卸载时执行)
return () => {
console.log('组件卸载,清理资源');
};
}, [userId]); // 依赖数组:只在userId变化时重新执行
if (loading) return <div>加载中...</div>;
if (!user) return <div>用户不存在</div>;
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
useRef - DOM引用
import { useRef } from 'react';
function TextInput() {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={focusInput}>聚焦输入框</button>
</div>
);
}
实战项目:待办事项应用
import { useState } from 'react';
import './App.css';
function App() {
const [todos, setTodos] = useState([]);
const [input, setInput] = useState('');
const [filter, setFilter] = useState('all'); // all, active, completed
const addTodo = () => {
if (!input.trim()) return;
setTodos([...todos, {
id: Date.now(),
text: input,
completed: false
}]);
setInput('');
};
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
));
};
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
const filteredTodos = todos.filter(todo => {
if (filter === 'active') return !todo.completed;
if (filter === 'completed') return todo.completed;
return true;
});
return (
<div className="app">
<h1>📝 我的待办事项</h1>
<div className="input-area">
<input
value={input}
onChange={e => setInput(e.target.value)}
onKeyPress={e => e.key === 'Enter' && addTodo()}
placeholder="添加新任务..."
/>
<button onClick={addTodo}>添加</button>
</div>
<div className="filters">
<button onClick={() => setFilter('all')}>全部</button>
<button onClick={() => setFilter('active')}>进行中</button>
<button onClick={() => setFilter('completed')}>已完成</button>
</div>
<ul className="todo-list">
{filteredTodos.map(todo => (
<li key={todo.id} className={todo.completed ? 'completed' : ''}>
<span onClick={() => toggleTodo(todo.id)}>{todo.text}</span>
<button onClick={() => deleteTodo(todo.id)}>删除</button>
</li>
))}
</ul>
<p className="count">
共 {todos.length} 项,已完成 {todos.filter(t => t.completed).length} 项
</p>
</div>
);
}
export default App;
总结
React的核心概念包括:
- JSX - 在JS中编写UI
- 组件 - UI的基本构建单元
- Props - 组件间传递数据
- State - 组件内部状态管理
- Hooks - 在函数组件中使用状态和副作用
掌握这些基础后,你可以继续学习React Router(路由)、Redux/Zustand(状态管理)、Next.js(框架)等进阶内容。