Files

359 lines
9.1 KiB
Markdown
Raw Permalink Normal View History

2025-06-13 16:30:38 +08:00
# 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 语法扩展,必须包含在一个根元素中。示例:
```jsx
const element = (
<div>
<h1>Hello, world!</h1>
<p>Welcome to React.</p>
</div>
);
```
#### 3. 表达式嵌入
在 JSX 中可以使用花括号 `{}` 嵌入 JavaScript 表达式。示例:
```jsx
const name = 'Alice';
const element = <h1>Hello, {name}</h1>;
```
#### 4. 样式处理
在 JSX 中使用 `style` 属性设置内联样式,属性值为一个 JavaScript 对象,键采用驼峰命名法。示例:
```jsx
const element = <div style={{ color: 'blue', fontSize: '20px' }}>Styled text</div>;
```
#### 5. 类名设置
由于 `class` 是 JavaScript 保留字,在 JSX 中使用 `className` 来设置 HTML 元素的类名。示例:
```jsx
const element = <div className="container">Container element</div>;
```
### 1.2.2 组件
#### 1. 函数组件
函数组件是一个返回 JSX 的 JavaScript 函数,接收 `props` 作为参数。示例:
```jsx
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
```
#### 2. 类组件
类组件继承自 `React.Component`,必须实现 `render` 方法返回 JSX。示例:
```jsx
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
```
### 1.2.6 事件处理
在 React 中,事件处理与 HTML 类似,但采用驼峰命名法,并且通过传递函数来处理事件。示例:
```jsx
function Button() {
const handleClick = () => {
alert('Button clicked!');
};
return (
<button onClick={handleClick}>Click me</button>
);
}
```
### 1.2.7 条件渲染
在 React 中可以使用 JavaScript 逻辑进行条件渲染。示例:
```jsx
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <h1>Welcome back!</h1>;
}
return <h1>Please sign up.</h1>;
}
```
还可以使用三元运算符和逻辑与运算符进行条件渲染:
```jsx
// 三元运算符
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. 示例:
```jsx
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` 和回调函数,实现子组件与父组件之间的状态同步。
```jsx
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,用于在函数组件中添加状态。示例如下:
```jsx
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。示例如下:
```jsx
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. 示例:
```jsx
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 示例
```jsx
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`
用于优化函数组件,避免不必要的渲染。
```jsx
const MyComponent = React.memo(function MyComponent(props) {
/* 使用 props 渲染 */
});
```
### 1.6.2 `useCallback` 和 `useMemo`
1. `useCallback`:缓存函数,避免每次渲染都重新创建。
- **原理**`useCallback` 接收一个回调函数和依赖项数组作为参数,返回一个 memoized 版本的回调函数,该回调函数仅在某个依赖项改变时才会更新。这有助于在传递回调函数给子组件时,避免不必要的重新渲染。
- **使用场景**:当你将回调函数作为 props 传递给子组件,并且子组件使用 `React.memo` 进行优化时,使用 `useCallback` 可以确保子组件不会因为回调函数的变化而不必要地重新渲染。
- **示例代码**
```jsx
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>
);
});
```
2. `useMemo`:缓存计算结果,避免重复计算。
- **原理**`useMemo` 接收一个计算函数和依赖项数组作为参数,返回一个 memoized 的计算结果。仅当某个依赖项改变时,才会重新执行计算函数。
- **使用场景**:当你有一个计算开销较大的函数,并且该函数的输入依赖于某些状态或 props 时,使用 `useMemo` 可以避免在每次渲染时都重新计算结果。
- **示例代码**
```jsx
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>
);
}
```