电商网站开发教程
1. React 简介和特性
1.1 React 是什么?
React 是一个用于构建用户界面的 JavaScript 库。它由 Facebook 开发并维护,广泛用于构建单页应用(SPA)和复杂的用户界面。
1.2 React 的主要特性
- 组件化:React 将 UI 拆分为独立的、可重用的组件。
- 虚拟 DOM:React 使用虚拟 DOM 来优化性能,减少直接操作真实 DOM 的次数。
- 单向数据流:数据在组件树中只能从父组件流向子组件。
2. 环境搭建
2.1 安装 Node.js 和 npm
首先,你需要安装 Node.js 和 npm(Node 包管理器)。你可以从 Node.js 官网 下载并安装。
2.2 使用 Create React App
Create React App 是一个官方推荐的工具链,用于快速搭建 React 项目。
npx create-react-app my-ecommerce-app
cd my-ecommerce-app
npm start
3. JSX 语法
3.1 什么是 JSX?
JSX 是一种 JavaScript 的语法扩展,允许你在 JavaScript 中编写类似 HTML 的代码。
const element = <h1>Hello, world!</h1>;
3.2 JSX 的优点
- 可读性高:JSX 使代码更接近 HTML,易于理解和维护。
- 灵活性:可以在 JSX 中嵌入 JavaScript 表达式。
4. 组件基础
4.1 函数组件
函数组件是一个简单的 JavaScript 函数,返回 JSX。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
4.2 类组件
类组件是使用 ES6 类定义的组件。
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
5. Props 和 State
5.1 Props
Props 是组件的输入参数,用于从父组件向子组件传递数据。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
5.2 State
State 是组件内部的状态,用于管理组件的动态数据。
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = { date: new Date() };
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
6. 生命周期方法
6.1 常用生命周期方法
componentDidMount:组件挂载后调用。componentDidUpdate:组件更新后调用。componentWillUnmount:组件卸载前调用。
class Clock extends React.Component {
componentDidMount() {
this.timerID = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
7. 事件处理
7.1 事件绑定
在 React 中,事件处理函数可以通过 onClick 等属性绑定。
function ActionButton() {
function handleClick() {
alert('Button clicked!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}
8. 条件渲染
8.1 使用条件运算符
你可以使用 JavaScript 的条件运算符来实现条件渲染。
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
return (
<div>
{isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please sign up.</h1>}
</div>
);
}
9. 列表和 Keys
9.1 渲染列表
你可以使用 map 函数来渲染列表。
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
9.2 Keys
Keys 帮助 React 识别哪些元素改变了,添加了,或者删除了。
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
10. 表单处理
10.1 受控组件
受控组件是指其值由 React 控制的表单元素。
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = { value: '' };
}
handleChange = (event) => {
this.setState({ value: event.target.value });
}
handleSubmit = (event) => {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
}
11. 组合 vs 继承
11.1 组合
React 推荐使用组合而非继承来实现代码复用。
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
12. 高阶组件 (HOC)
12.1 什么是 HOC?
高阶组件是一个函数,接收一个组件并返回一个新的组件。
function withSubscription(WrappedComponent, selectData) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
data: selectData(DataSource, props)
};
}
render() {
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
}
13. Render Props
13.1 什么是 Render Props?
Render Props 是一种通过函数 prop 来共享代码的技术。
class MouseTracker extends React.Component {
render() {
return (
<div>
<h1>Move the mouse around!</h1>
<Mouse render={mouse => (
<Cat mouse={mouse} />
)}/>
</div>
);
}
}
14. Context API
14.1 什么是 Context API?
Context API 提供了一种在组件树中共享数据的方式,无需手动通过 props 传递。
const ThemeContext = React.createContext('light');
class App extends React.Component {
render() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
15. Refs 和 DOM
15.1 什么是 Refs?
Refs 提供了一种访问 DOM 节点或 React 元素的方式。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
render() {
return <div ref={this.myRef} />;
}
}
16. useState 和 useEffect
16.1 useState
useState 是一个 Hook,用于在函数组件中添加状态。
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
16.2 useEffect
useEffect 是一个 Hook,用于在函数组件中执行副作用操作。
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
17. useContext
17.1 使用 useContext
useContext 是一个 Hook,用于在函数组件中使用 Context API。
const ThemeContext = React.createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Toolbar() {
const theme = useContext(ThemeContext);
return (
<div>
<ThemedButton />
</div>
);
}
18. useReducer
18.1 使用 useReducer
useReducer 是一个 Hook,用于在函数组件中管理复杂的状态逻辑。
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
19. 自定义 Hooks
19.1 创建自定义 Hook
自定义 Hook 是一个函数,名称以 use 开头,可以在其中使用其他 Hooks。
function useFriendStatus(friendID) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
};
});
return isOnline;
}
20. Hooks 规则和最佳实践
20.1 规则
- 只在顶层调用 Hooks。
- 只在 React 函数组件和自定义 Hooks 中调用 Hooks。
20.2 最佳实践
- 使用
useEffect来管理副作用。 - 使用
useContext来共享全局状态。
21. Redux 基础
21.1 什么是 Redux?
Redux 是一个用于管理应用状态的 JavaScript 库。
21.2 核心概念
- Store:存储应用状态的对象。
- Action:描述状态变化的简单对象。
- Reducer:纯函数,根据 Action 更新 Store。
const store = createStore(reducer);
store.dispatch({ type: 'INCREMENT' });
22. Redux Toolkit
22.1 使用 Redux Toolkit
Redux Toolkit 是 Redux 的官方工具集,简化了 Redux 的使用。
import { createSlice, configureStore } from '@reduxjs/toolkit';
const counterSlice = createSlice({
name: 'counter',
initialState: 0,
reducers: {
increment: state => state + 1,
decrement: state => state - 1
}
});
const store = configureStore({
reducer: counterSlice.reducer
});
23. MobX 简介
23.1 什么是 MobX?
MobX 是一个简单、可扩展的状态管理库。
23.2 核心概念
- Observable:可观察的状态。
- Action:改变状态的操作。
- Reaction:自动响应状态变化的副作用。
import { observable, action, makeObservable } from 'mobx';
class Counter {
count = 0;
constructor() {
makeObservable(this, {
count: observable,
increment: action,
decrement: action
});
}
increment() {
this.count++;
}
decrement() {
this.count--;
}
}
24. Recoil 入门
24.1 什么是 Recoil?
Recoil 是一个用于 React 的状态管理库,由 Facebook 开发。
24.2 核心概念
- Atom:存储状态的基本单位。
- Selector:派生状态的纯函数。
import { atom, selector, useRecoilState, useRecoilValue } from 'recoil';
const counterState = atom({
key: 'counterState',
default: 0
});
const doubleCountState = selector({
key: 'doubleCountState',
get: ({get}) => get(counterState) * 2
});
25. 状态管理最佳实践
25.1 选择合适的状态管理工具
- 对于小型应用,可以使用 React 的
useState和useReducer。 - 对于大型应用,可以考虑使用 Redux、MobX 或 Recoil。
25.2 保持状态的单一来源
确保应用的状态只有一个来源,避免状态分散在多个组件中。
26. React Router 基础
26.1 安装 React Router
npm install react-router-dom
26.2 基本用法
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
function App() {
return (
<Router>
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/users">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
);
}
27. 动态路由
27.1 动态路由参数
你可以使用 : 来定义动态路由参数。
<Route path="/users/:id">
<User />
</Route>
27.2 获取路由参数
使用 useParams Hook 获取路由参数。
import { useParams } from 'react-router-dom';
function User() {
let { id } = useParams();
return <h1>User: {id}</h1>;
}
28. 嵌套路由
28.1 嵌套路由
你可以在组件中嵌套 Route 组件来实现嵌套路由。