文档
Preact Hello World — React 兼容的轻量应用
目标
展示 Preact 与 React 几乎相同的 API,同时强调其 3KB 的体量优势。包含 Hooks、组件和兼容模式示例。
完整代码
// src/main.jsx
import { render } from "preact";
import { App } from "./App";
import "./style.css";
render(<App />, document.getElementById("app"));
// src/App.jsx
import { useState, useEffect, useCallback, useMemo, useRef } from "preact/hooks";
export function App() {
const [count, setCount] = useState(0);
const [name, setName] = useState("朋友");
const [theme, setTheme] = useState("light");
const inputRef = useRef(null);
// useEffect — 与 React 完全一致
useEffect(() => {
document.title = `Preact App - ${count} 次点击`;
}, [count]);
// useMemo — 自动优化
const doubleCount = useMemo(() => count * 2, [count]);
// useCallback — 缓存回调
const focusInput = useCallback(() => {
inputRef.current?.focus();
}, []);
return (
<div className={`app ${theme}`}>
<h1>⚛️ Preact Demo</h1>
<p className="subtitle">
仅 <strong>3KB</strong> 的 React 替代方案
</p>
{/* 双向绑定 */}
<div className="input-group">
<input
ref={inputRef}
value={name}
onInput={(e) => setName(e.currentTarget.value)}
placeholder="你的名字..."
/>
<button onClick={focusInput}>聚焦输入框</button>
</div>
<p className="greeting">
你好,<strong>{name}</strong>!
</p>
{/* 计数器 */}
<div className="counter">
<h2>{count}</h2>
<p>2倍数:{doubleCount}</p>
<div className="buttons">
<button onClick={() => setCount((c) => c + 1)}>+1</button>
<button onClick={() => setCount((c) => c - 1)}>-1</button>
<button onClick={() => setCount(0)}>重置</button>
</div>
</div>
{/* 主题切换 */}
<button
className="theme-toggle"
onClick={() => setTheme((t) => (t === "light" ? "dark" : "light"))}
>
切换主题({theme})
</button>
{/* 条件渲染 */}
{count >= 10 && (
<div className="achievement">🏆 达到 10 次点击!</div>
)}
</div>
);
}
/* src/style.css */
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, 'Microsoft YaHei', sans-serif; }
.app {
max-width: 480px; margin: 40px auto; padding: 0 16px;
text-align: center; border-radius: 16px; padding: 32px;
transition: background 0.3s, color 0.3s;
}
.app.light { background: #fff; color: #1a1a2e; }
.app.dark { background: #1a1a2e; color: #eee; }
.subtitle { color: #888; margin: 8px 0 24px; }
.input-group {
display: flex; gap: 8px; margin-bottom: 16px;
}
.input-group input {
flex: 1; padding: 10px; border: 2px solid #e2e8f0;
border-radius: 8px; font-size: 1rem;
}
.input-group button {
padding: 10px 16px; border: none; border-radius: 8px;
background: #6366f1; color: white; cursor: pointer;
}
.counter h2 { font-size: 3rem; margin: 8px 0; }
.buttons button {
padding: 10px 20px; border: none; border-radius: 8px;
font-size: 1rem; cursor: pointer; margin: 4px;
background: #10b981; color: white;
transition: transform 0.15s;
}
.buttons button:hover { transform: translateY(-1px); }
.theme-toggle {
margin-top: 20px; padding: 8px 20px;
border: 1px solid #ccc; border-radius: 8px;
background: transparent; cursor: pointer; font-size: 0.9rem;
}
.achievement {
margin-top: 16px; padding: 12px;
background: #fef3c7; border-radius: 8px; font-weight: 600;
}
<!-- index.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Preact App</title>
</head>
<body>
<div id="app"></div>
<script src="./src/main.jsx" type="module"></script>
</body>
</html>
// package.json(关键字段)
{
"scripts": {
"dev": "vite",
"build": "vite build"
},
"dependencies": {
"preact": "^10.19.0"
},
"devDependencies": {
"@preact/preset-vite": "^2.7.0",
"vite": "^5.0.0"
}
}
运行步骤
npm install
npm run dev
预期输出
- 界面与 React 几乎无法区分
- 打包后 gzip 体积约 4KB(Preact 3KB + 组件代码)
- 计数器、双向绑定、主题切换、条件渲染均正常工作