使用 React 组件
MDX
文件中直接使用 React Hooks 来构建 React 组件。
示例
Counter
组件,然后通过 <Counter />
进行使用。
Copy
Ask AI
export const Counter = () => {
const [count, setCount] = useState(0)
const increment = () => setCount(count + 1)
const decrement = () => setCount(count - 1)
return (
<div className="flex items-center justify-center">
<div className="flex items-center rounded-xl overflow-hidden border border-zinc-950/20 dark:border-white/20">
<button
onClick={decrement}
className="flex items-center justify-center h-8 w-8 text-zinc-950/80 dark:text-white/80 border-r border-zinc-950/20 dark:border-white/20"
aria-label="Decrease"
>
-
</button>
<div className="flex text-sm items-center justify-center h-8 px-6 text-zinc-950/80 dark:text-white/80 font-medium min-w-[4rem] text-center">
{count}
</div>
<button
onClick={increment}
className="flex items-center justify-center h-8 w-8 text-zinc-950/80 dark:text-white/80 border-l border-zinc-950/20 dark:border-white/20"
aria-label="Increase"
>
+
</button>
</div>
</div>
)
}
<Counter />
导入组件
snippets
文件夹导入组件。与常规 React 不同,你不能从任意 MDX
文件导入组件。可复用组件必须从 snippets
文件夹内的文件进行引用。了解更多:可复用片段。
示例
ColorGenerator
组件,并在一个 MDX
文件中引用它。
在 snippets
文件夹中创建 color-generator.jsx
文件:
/snippets/color-generator.jsx
Copy
Ask AI
export const ColorGenerator = () => {
const [hue, setHue] = useState(180)
const [saturation, setSaturation] = useState(50)
const [lightness, setLightness] = useState(50)
const [colors, setColors] = useState([])
useEffect(() => {
const newColors = []
for (let i = 0; i < 5; i++) {
const l = Math.max(10, Math.min(90, lightness - 20 + i * 10))
newColors.push(`hsl(${hue}, ${saturation}%, ${l}%)`)
}
setColors(newColors)
}, [hue, saturation, lightness])
const copyToClipboard = (color) => {
navigator.clipboard
.writeText(color)
.then(() => {
console.log(`已将 ${color} 复制到剪贴板!`)
})
.catch((err) => {
console.error("复制失败:", err)
})
}
return (
<div className="p-4 border dark:border-zinc-950/80 rounded-xl not-prose">
<div className="space-y-4">
<div className="space-y-2">
<label className="block text-sm text-zinc-950/70 dark:text-white/70">
色相:{hue}°
<input
type="range"
min="0"
max="360"
value={hue}
onChange={(e) => setHue(Number.parseInt(e.target.value))}
className="w-full h-2 bg-zinc-950/20 rounded-lg appearance-none cursor-pointer dark:bg-white/20 mt-1"
style={{
background: `linear-gradient(to right,
hsl(0, ${saturation}%, ${lightness}%),
hsl(60, ${saturation}%, ${lightness}%),
hsl(120, ${saturation}%, ${lightness}%),
hsl(180, ${saturation}%, ${lightness}%),
hsl(240, ${saturation}%, ${lightness}%),
hsl(300, ${saturation}%, ${lightness}%),
hsl(360, ${saturation}%, ${lightness}%))`,
}}
/>
</label>
<label className="block text-sm text-zinc-950/70 dark:text-white/70">
饱和度:{saturation}%
<input
type="range"
min="0"
max="100"
value={saturation}
onChange={(e) => setSaturation(Number.parseInt(e.target.value))}
className="w-full h-2 bg-zinc-950/20 rounded-lg appearance-none cursor-pointer dark:bg-white/20 mt-1"
style={{
background: `linear-gradient(to right,
hsl(${hue}, 0%, ${lightness}%),
hsl(${hue}, 50%, ${lightness}%),
hsl(${hue}, 100%, ${lightness}%))`,
}}
/>
</label>
<label className="block text-sm text-zinc-950/70 dark:text-white/70">
明度:{lightness}%
<input
type="range"
min="0"
max="100"
value={lightness}
onChange={(e) => setLightness(Number.parseInt(e.target.value))}
className="w-full h-2 bg-zinc-950/20 rounded-lg appearance-none cursor-pointer dark:bg-white/20 mt-1"
style={{
background: `linear-gradient(to right,
hsl(${hue}, ${saturation}%, 0%),
hsl(${hue}, ${saturation}%, 50%),
hsl(${hue}, ${saturation}%, 100%))`,
}}
/>
</label>
</div>
<div className="flex space-x-1">
{colors.map((color, idx) => (
<div
key={idx}
className="h-16 rounded flex-1 cursor-pointer transition-transform hover:scale-105"
style={{ backgroundColor: color }}
title={`点击以复制:${color}`}
onClick={() => copyToClipboard(color)}
/>
))}
</div>
<div className="text-sm font-mono text-zinc-950/70 dark:text-white/70">
<p>
基础色:hsl({hue}, {saturation}%, {lightness}%)
</p>
</div>
</div>
</div>
)
}
MDX
文件中导入并使用 ColorGenerator
组件:
Copy
Ask AI
import { ColorGenerator } from "/snippets/color-generator.jsx"
<ColorGenerator />
注意事项
客户端渲染的影响
客户端渲染的影响
React Hook 组件在客户端渲染,这会带来以下影响:
- SEO:搜索引擎可能无法完整索引动态内容。
- 初始加载:组件渲染前,访客可能会看到短暂的加载占位。
- 无障碍:确保动态内容的变化会被读屏软件正确宣读。
性能最佳实践
性能最佳实践
- 优化依赖数组:在
useEffect
的依赖数组中仅包含必要依赖。 - 记忆化复杂计算:对开销较大的操作使用
useMemo
或useCallback
。 - 减少重复渲染:将大型组件拆分为更小的组件,避免级联式重复渲染。
- 懒加载:考虑对复杂组件进行懒加载,以改善页面的初始加载时间。