Files
2025-06-13 16:30:38 +08:00

9.1 KiB
Raw Permalink Blame History

1. React

1.1 脚手架文件结构

├── node_modules 
├── public
│   ├── favicon.ico: 页签图标
│   └── index.html: 主页面
├── src
│   ├── assets: 存放静态资源
│   │   └── logo.svg
│   ├── components: 存放组件
│   │   └── HelloWorld.jsx
│   ├── App.jsx: 汇总所有组件
│   └── index.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── package.json: 应用包配置文件 
├── README.md: 应用描述文件
└── package-lock.json:包版本控制文件

1.2 React 核心概念

1.2.1 JSX

1. 定义

JSX 是 JavaScript XML 的缩写,它允许在 JavaScript 代码中编写类似 HTML 的结构,最终会被 Babel 等工具编译为 React 元素。

2. 基本语法

JSX 看起来像 HTML,但实际上是 JavaScript 语法扩展,必须包含在一个根元素中。示例:

const element = (
  <div>
    <h1>Hello, world!</h1>
    <p>Welcome to React.</p>
  </div>
);

3. 表达式嵌入

在 JSX 中可以使用花括号 {} 嵌入 JavaScript 表达式。示例:

const name = 'Alice';
const element = <h1>Hello, {name}</h1>;

4. 样式处理

在 JSX 中使用 style 属性设置内联样式,属性值为一个 JavaScript 对象,键采用驼峰命名法。示例:

const element = <div style={{ color: 'blue', fontSize: '20px' }}>Styled text</div>;

5. 类名设置

由于 class 是 JavaScript 保留字,在 JSX 中使用 className 来设置 HTML 元素的类名。示例:

const element = <div className="container">Container element</div>;

1.2.2 组件

1. 函数组件

函数组件是一个返回 JSX 的 JavaScript 函数,接收 props 作为参数。示例:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

2. 类组件

类组件继承自 React.Component,必须实现 render 方法返回 JSX。示例:

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

1.2.6 事件处理

在 React 中,事件处理与 HTML 类似,但采用驼峰命名法,并且通过传递函数来处理事件。示例:

function Button() {
  const handleClick = () => {
    alert('Button clicked!');
  };

  return (
    <button onClick={handleClick}>Click me</button>
  );
}

1.2.7 条件渲染

在 React 中可以使用 JavaScript 逻辑进行条件渲染。示例:

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <h1>Welcome back!</h1>;
  }
  return <h1>Please sign up.</h1>;
}

还可以使用三元运算符和逻辑与运算符进行条件渲染:

// 三元运算符
const element = isLoggedIn ? <LogoutButton /> : <LoginButton />;

// 逻辑与运算符
const unreadMessages = ['React', 'Re: React', 'Re:Re: React'];
const element = (
  <div>
    <h1>Hello!</h1>
    {unreadMessages.length > 0 && (
      <h2>You have {unreadMessages.length} unread messages.</h2>
    )}
  </div>
);

1.2.3 状态(State

  1. 功能:用于管理组件内部的数据。
  2. 示例:
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>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

1.2.4 生命周期方法

  1. componentDidMount():组件挂载后执行,常用于数据请求。
  2. componentDidUpdate():组件更新后执行。
  3. componentWillUnmount():组件卸载前执行,常用于清理工作。

1.2.5 状态提升

当多个组件需要共享状态时,通常会将状态提升到最近的共同父组件中。通过父组件传递 props 和回调函数,实现子组件与父组件之间的状态同步。

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>Count: {this.state.count}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}

1.3 React Hooks

1.3.1 useState

useState 是一个基础的 Hook,用于在函数组件中添加状态。示例如下:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

1.3.2 useEffect

useEffect 可以让你在函数组件中执行副作用操作,比如数据获取、订阅或手动修改 DOM。示例如下:

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

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  }, [count]);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

1.4 React 路由

1.4.1 基本使用

  1. 安装:npm install react-router-dom
  2. 示例:
import React from 'react';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';

function App() {
  return (
    <Router>
      <nav>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
        </ul>
      </nav>

      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </Router>
  );
}

function Home() {
  return <h1>Home Page</h1>;
}

function About() {
  return <h1>About Page</h1>;
}

1.5 React 上下文(Context

1.5.1 功能

用于在组件树中共享数据,避免逐层传递 props。

1.5.2 示例

import React, { createContext, useContext } from 'react';

const ThemeContext = createContext();

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button style={{ background: theme }}>I am styled by theme context!</button>;
}

1.6 React 优化

1.6.1 React.memo

用于优化函数组件,避免不必要的渲染。

const MyComponent = React.memo(function MyComponent(props) {
  /* 使用 props 渲染 */
});

1.6.2 useCallbackuseMemo

  1. useCallback:缓存函数,避免每次渲染都重新创建。
    • 原理useCallback 接收一个回调函数和依赖项数组作为参数,返回一个 memoized 版本的回调函数,该回调函数仅在某个依赖项改变时才会更新。这有助于在传递回调函数给子组件时,避免不必要的重新渲染。
    • 使用场景:当你将回调函数作为 props 传递给子组件,并且子组件使用 React.memo 进行优化时,使用 useCallback 可以确保子组件不会因为回调函数的变化而不必要地重新渲染。
    • 示例代码
import React, { useState, useCallback } from 'react';

function Parent() {
  const [count, setCount] = useState(0);
  const [value, setValue] = useState('');

  // 使用 useCallback 缓存函数
  const handleClick = useCallback(() => {
    console.log(`Count is: ${count}`);
  }, [count]);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
      <input value={value} onChange={(e) => setValue(e.target.value)} />
      <Child handleClick={handleClick} />
    </div>
  );
}

const Child = React.memo(function Child({ handleClick }) {
  return (
    <button onClick={handleClick}>Click me</button>
  );
});
  1. useMemo:缓存计算结果,避免重复计算。
    • 原理useMemo 接收一个计算函数和依赖项数组作为参数,返回一个 memoized 的计算结果。仅当某个依赖项改变时,才会重新执行计算函数。
    • 使用场景:当你有一个计算开销较大的函数,并且该函数的输入依赖于某些状态或 props 时,使用 useMemo 可以避免在每次渲染时都重新计算结果。
    • 示例代码
import React, { useState, useMemo } from 'react';

function App() {
  const [count, setCount] = useState(0);
  const [value, setValue] = useState('');

  // 使用 useMemo 缓存计算结果
  const expensiveValue = useMemo(() => {
    console.log('Calculating expensive value...');
    let sum = 0;
    for (let i = 0; i < count; i++) {
      sum += i;
    }
    return sum;
  }, [count]);

  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Increment Count</button>
      <input value={value} onChange={(e) => setValue(e.target.value)} />
      <p>Expensive Value: {expensiveValue}</p>
    </div>
  );
}