核心差异 #
一、体积对比 #
1.1 包大小 #
text
React 18.x
├── react ~42KB (gzip ~12KB)
├── react-dom ~130KB (gzip ~42KB)
└── 总计 ~172KB (gzip ~54KB)
Preact 10.x
├── preact ~10KB (gzip ~3KB)
└── 总计 ~10KB (gzip ~3KB)
1.2 体积差异原因 #
| 方面 | Preact | React |
|---|---|---|
| 合成事件 | 无 | 有 |
| 事件池 | 无 | 有 |
| 平台抽象 | 简化 | 完整 |
| 调试工具 | 可选 | 内置 |
二、事件系统 #
2.1 事件处理 #
jsx
// React: 合成事件
function ReactComponent() {
const handleClick = (e) => {
e.preventDefault();
// e 是 SyntheticEvent
console.log(e.nativeEvent); // 原生事件
};
return <button onClick={handleClick}>Click</button>;
}
// Preact: 原生事件
function PreactComponent() {
const handleClick = (e) => {
e.preventDefault();
// e 是原生 Event
console.log(e); // 直接是原生事件
};
return <button onClick={handleClick}>Click</button>;
}
2.2 事件差异 #
| 方面 | Preact | React |
|---|---|---|
| 事件类型 | 原生 Event | SyntheticEvent |
| 事件池 | 无 | 有(已废弃) |
| e.persist() | 不需要 | 需要(旧版本) |
| 性能 | 更快 | 略慢 |
2.3 事件命名 #
jsx
// 两者相同
<button onClick={handleClick} />
<input onChange={handleChange} />
<form onSubmit={handleSubmit} />
三、DOM 属性 #
3.1 class vs className #
jsx
// React: 必须使用 className
<div className="container">Content</div>
// Preact: 两种都支持
<div className="container">Content</div>
<div class="container">Content</div> // 推荐
3.2 for vs htmlFor #
jsx
// React: 必须使用 htmlFor
<label htmlFor="email">Email</label>
// Preact: 两种都支持
<label htmlFor="email">Email</label>
<label for="email">Email</label> // 推荐
3.3 style 属性 #
jsx
// 两者相同
<div style={{ color: 'red', fontSize: '16px' }}>Text</div>
四、生命周期 #
4.1 类组件生命周期 #
jsx
// React 完整生命周期
class ReactComponent extends React.Component {
constructor(props) {}
static getDerivedStateFromProps(props, state) {}
shouldComponentUpdate(nextProps, nextState) {}
render() {}
getSnapshotBeforeUpdate(prevProps, prevState) {}
componentDidMount() {}
componentDidUpdate(prevProps, prevState, snapshot) {}
componentWillUnmount() {}
static getDerivedStateFromError(error) {}
componentDidCatch(error, info) {}
}
// Preact 简化生命周期
class PreactComponent extends Component {
constructor(props) {}
static getDerivedStateFromProps(props, state) {}
shouldComponentUpdate(nextProps, nextState) {}
render() {}
componentDidMount() {}
componentDidUpdate(prevProps, prevState) {}
componentWillUnmount() {}
static getDerivedStateFromError(error) {}
componentDidCatch(error) {}
}
4.2 生命周期差异 #
| 方法 | Preact | React |
|---|---|---|
| getSnapshotBeforeUpdate | ❌ | ✅ |
| componentDidCatch info | ❌ | ✅ |
| getDerivedStateFromError | ✅ | ✅ |
五、Hooks #
5.1 Hooks 支持 #
jsx
// 两者基本相同
import { useState, useEffect, useContext, useRef } from 'preact/hooks';
// 或
import { useState, useEffect, useContext, useRef } from 'react';
5.2 Preact 特有 Hooks #
jsx
// Preact 提供额外的 Hooks
import {
useErrorBoundary, // 错误边界 Hook
useReducer,
useMemo,
useCallback,
useLayoutEffect,
useImperativeHandle
} from 'preact/hooks';
// useErrorBoundary 示例
function ErrorBoundary({ children }) {
const [error, resetError] = useErrorBoundary();
if (error) {
return (
<div>
<p>Error: {error.message}</p>
<button onClick={resetError}>Retry</button>
</div>
);
}
return children;
}
六、Refs #
6.1 创建 Ref #
jsx
// React
import { createRef, useRef } from 'react';
class Component extends React.Component {
inputRef = createRef();
render() {
return <input ref={this.inputRef} />;
}
}
// Preact
import { createRef, useRef } from 'preact';
class Component extends Component {
inputRef = createRef();
render() {
return <input ref={this.inputRef} />;
}
}
6.2 forwardRef #
jsx
// 两者相同
import { forwardRef } from 'preact';
// 或
import { forwardRef } from 'react';
const Input = forwardRef((props, ref) => {
return <input ref={ref} {...props} />;
});
七、Context #
7.1 Context API #
jsx
// React
import { createContext, useContext } from 'react';
const ThemeContext = createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>
);
}
// Preact
import { createContext, useContext } from 'preact';
const ThemeContext = createContext('light');
function App() {
return (
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>
);
}
7.2 Context 差异 #
| 方面 | Preact | React |
|---|---|---|
| createContext | ✅ | ✅ |
| Provider | ✅ | ✅ |
| Consumer | ✅ | ✅ |
| useContext | ✅ | ✅ |
八、Portals #
8.1 Portal 实现 #
jsx
// React
import { createPortal } from 'react-dom';
function Modal({ children }) {
return createPortal(
<div class="modal">{children}</div>,
document.body
);
}
// Preact
import { createPortal } from 'preact';
function Modal({ children }) {
return createPortal(
<div class="modal">{children}</div>,
document.body
);
}
九、错误边界 #
9.1 类组件错误边界 #
jsx
// React
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.log(errorInfo.componentStack);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
// Preact
class ErrorBoundary extends Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error) {
console.log(error);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
9.2 函数组件错误边界 #
jsx
// Preact 特有
import { useErrorBoundary } from 'preact/hooks';
function ErrorBoundary({ children }) {
const [error, resetError] = useErrorBoundary();
if (error) {
return (
<div>
<p>Error: {error.message}</p>
<button onClick={resetError}>Retry</button>
</div>
);
}
return children;
}
十、性能对比 #
10.1 基准测试 #
text
操作 Preact React
首次渲染 ~5ms ~15ms
更新 ~2ms ~5ms
内存占用 ~1MB ~4MB
10.2 性能差异原因 #
| 方面 | Preact | React |
|---|---|---|
| 事件系统 | 原生 | 合成 |
| 虚拟DOM | 简化 | 完整 |
| Diff算法 | 优化 | 标准 |
| 包体积 | 小 | 大 |
十一、生态系统 #
11.1 官方库 #
| 库 | Preact | React |
|---|---|---|
| 路由 | preact-router | react-router |
| 状态 | signals | redux/zustand |
| SSR | preact-render-to-string | next.js |
| CLI | preact-cli | create-react-app |
11.2 兼容性 #
jsx
// 使用 preact/compat 兼容 React 库
import { render } from 'preact';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
function App() {
return (
<Provider store={store}>
<BrowserRouter>
<Main />
</BrowserRouter>
</Provider>
);
}
十二、选择建议 #
12.1 选择 Preact #
- 追求极致性能
- 包体积敏感
- 移动端应用
- 渐进式增强
- 微前端子应用
12.2 选择 React #
- 大型企业应用
- 需要完整生态
- 团队熟悉 React
- 需要社区支持
- 复杂项目需求
十三、总结 #
| 方面 | Preact | React |
|---|---|---|
| 体积 | 3KB | 54KB |
| 事件 | 原生 | 合成 |
| 性能 | 更快 | 快 |
| 生态 | 兼容 | 完整 |
| 学习 | 简单 | 中等 |
核心差异:
- Preact 更轻量、更快
- React 生态更完善
- 通过 compat 可兼容 React 库
- 根据项目需求选择
最后更新:2026-03-28