React 框架教程

1. React 简介

React 是由 Facebook 开发的用于构建用户界面的 JavaScript 库。它采用组件化的开发模式,使得构建复杂的用户界面变得更加容易和高效。

2. 创建 React 应用

使用 Create React App

# 全局安装 Create React App
npm install -g create-react-app

# 创建新项目
npx create-react-app my-app

# 进入项目目录
cd my-app

# 启动开发服务器
npm start

3. JSX 语法

JSX 是 JavaScript 的语法扩展,允许我们在 JavaScript 中写类似 HTML 的代码。

// JSX 基本语法
function Welcome(props) {
    return <h1>你好,{props.name}!</h1>;
}

// 在 JSX 中使用表达式
const name = "张三";
const element = <h1>你好,{name}!</h1>;

// 条件渲染
function Greeting(props) {
    if (props.isLoggedIn) {
        return <h1>欢迎回来!</h1>;
    }
    return <h1>请先登录。</h1>;
}

// 列表渲染
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
    <li key={number}>{number}</li>
);

4. 组件

函数组件

// 函数组件
function Welcome(props) {
    return <h1>你好,{props.name}!</h1>;
}

// 使用箭头函数
const Welcome = (props) => {
    return <h1>你好,{props.name}!</h1>;
};

// 简化版本
const Welcome = ({ name }) => <h1>你好,{name}!</h1>;

类组件

// 类组件
class Welcome extends React.Component {
    render() {
        return <h1>你好,{this.props.name}!</h1>;
    }
}

// 带状态的类组件
class Counter extends React.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}>增加</button>
            </div>
        );
    }
}

5. Hooks

Hooks 是 React 16.8 的新增特性,让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

useState

import React, { useState } from 'react';

function Counter() {
    const [count, setCount] = useState(0);
    
    return (
        <div>
            <p>你点击了 {count} 次</p>
            <button onClick={() => setCount(count + 1)}>
                点击我
            </button>
        </div>
    );
}

// 多个状态值
function UserProfile() {
    const [name, setName] = useState('');
    const [age, setAge] = useState(0);
    const [email, setEmail] = useState('');
    
    return (
        <form>
            <input 
                value={name} 
                onChange={(e) => setName(e.target.value)} 
                placeholder="姓名"
            />
            <input 
                value={age} 
                onChange={(e) => setAge(e.target.value)} 
                placeholder="年龄"
                type="number"
            />
            <input 
                value={email} 
                onChange={(e) => setEmail(e.target.value)} 
                placeholder="邮箱"
                type="email"
            />
        </form>
    );
}

useEffect

import React, { useState, useEffect } from 'react';

function Timer() {
    const [seconds, setSeconds] = useState(0);
    
    useEffect(() => {
        const interval = setInterval(() => {
            setSeconds(seconds => seconds + 1);
        }, 1000);
        
        // 清理函数
        return () => clearInterval(interval);
    }, []); // 空依赖数组,只在组件挂载时执行
    
    return <div>已运行 {seconds} 秒</div>;
}

// 监听特定状态变化
function UserData({ userId }) {
    const [user, setUser] = useState(null);
    
    useEffect(() => {
        fetchUser(userId).then(setUser);
    }, [userId]); // 当 userId 变化时重新执行
    
    return user ? <div>{user.name}</div> : <div>加载中...</div>;
}

6. 事件处理

function Button() {
    // 事件处理函数
    const handleClick = (e) => {
        e.preventDefault();
        console.log('按钮被点击了');
    };
    
    // 带参数的事件处理
    const handleClickWithParam = (param) => {
        console.log('参数:', param);
    };
    
    return (
        <div>
            <button onClick={handleClick}>点击我</button>
            <button onClick={() => handleClickWithParam('hello')}>
                带参数点击
            </button>
        </div>
    );
}

// 表单处理
function Form() {
    const [formData, setFormData] = useState({
        name: '',
        email: ''
    });
    
    const handleChange = (e) => {
        const { name, value } = e.target;
        setFormData(prev => ({
            ...prev,
            [name]: value
        }));
    };
    
    const handleSubmit = (e) => {
        e.preventDefault();
        console.log('表单数据:', formData);
    };
    
    return (
        <form onSubmit={handleSubmit}>
            <input
                name="name"
                value={formData.name}
                onChange={handleChange}
                placeholder="姓名"
            />
            <input
                name="email"
                value={formData.email}
                onChange={handleChange}
                placeholder="邮箱"
                type="email"
            />
            <button type="submit">提交</button>
        </form>
    );
}

7. 组件间通信

Props 传递

// 父组件向子组件传递数据
function Parent() {
    const [message, setMessage] = useState('Hello from Parent');
    
    return (
        <div>
            <Child message={message} />
            <button onClick={() => setMessage('Updated!')}>
                更新消息
            </button>
        </div>
    );
}

function Child({ message }) {
    return <p>{message}</p>;
}

// 子组件向父组件传递数据(回调函数)
function Parent() {
    const [count, setCount] = useState(0);
    
    const handleIncrement = () => {
        setCount(count + 1);
    };
    
    return (
        <div>
            <p>计数:{count}</p>
            <Child onIncrement={handleIncrement} />
        </div>
    );
}

function Child({ onIncrement }) {
    return <button onClick={onIncrement}>增加</button>;
}

8. 状态管理

useReducer

import React, { useReducer } from 'react';

// 定义 reducer 函数
const counterReducer = (state, action) => {
    switch (action.type) {
        case 'increment':
            return { count: state.count + 1 };
        case 'decrement':
            return { count: state.count - 1 };
        case 'reset':
            return { count: 0 };
        default:
            throw new Error();
    }
};

function Counter() {
    const [state, dispatch] = useReducer(counterReducer, { count: 0 });
    
    return (
        <div>
            <p>计数: {state.count}</p>
            <button onClick={() => dispatch({ type: 'increment' })}>
                +
            </button>
            <button onClick={() => dispatch({ type: 'decrement' })}>
                -
            </button>
            <button onClick={() => dispatch({ type: 'reset' })}>
                重置
            </button>
        </div>
    );
}

9. 条件渲染和列表渲染

// 条件渲染
function Greeting({ isLoggedIn, user }) {
    return (
        <div>
            {isLoggedIn ? (
                <h1>欢迎回来,{user.name}!</h1>
            ) : (
                <h1>请登录</h1>
            )}
        </div>
    );
}

// 列表渲染
function TodoList({ todos }) {
    return (
        <ul>
            {todos.map(todo => (
                <li key={todo.id}>
                    <span style={{ 
                        textDecoration: todo.completed ? 'line-through' : 'none' 
                    }}>
                        {todo.text}
                    </span>
                </li>
            ))}
        </ul>
    );
}

// 使用示例
function App() {
    const [todos, setTodos] = useState([
        { id: 1, text: '学习 React', completed: false },
        { id: 2, text: '写代码', completed: true },
        { id: 3, text: '休息', completed: false }
    ]);
    
    return <TodoList todos={todos} />;
}

10. 样式处理

// 内联样式
function Button() {
    const buttonStyle = {
        backgroundColor: '#007bff',
        color: 'white',
        padding: '10px 20px',
        border: 'none',
        borderRadius: '4px',
        cursor: 'pointer'
    };
    
    return <button style={buttonStyle}>点击我</button>;
}

// CSS 类名
function Card({ className }) {
    return (
        <div className={`card ${className}`}>
            <div className="card-body">
                <h5 className="card-title">卡片标题</h5>
                <p className="card-text">卡片内容</p>
            </div>
        </div>
    );
}

// 条件样式
function StatusBadge({ status }) {
    const badgeClass = `badge ${
        status === 'success' ? 'badge-success' : 
        status === 'error' ? 'badge-error' : 
        'badge-default'
    }`;
    
    return <span className={badgeClass}>{status}</span>;
}

11. 总结

React 是一个强大的前端库,掌握了组件、状态管理、事件处理等核心概念后,你就可以构建复杂的用户界面了。建议通过实际项目来加深理解,并学习 React 生态系统中的其他工具如 React Router、Redux 等。