Skeleton
Skeleton 从 HeroUI v2 到 v3 的迁移指南。
完整的 API 参考、样式指南与高级示例请参阅 v3 Skeleton 文档。本指南只关注从 HeroUI v2 的迁移。
结构变化
在 v2 中,Skeleton 会包裹其子节点,并根据 isLoaded 显示或隐藏:
import { Skeleton } from "@heroui/react";
export default function App() {
const isLoaded = false;
return (
<Skeleton isLoaded={isLoaded}>
<div className="h-24 bg-secondary" />
</Skeleton>
);
}在 v3 中,Skeleton 改为独立的占位符,由你自己手动控制其可见性:
import { Skeleton } from "@heroui/react";
export default function App() {
const isLoaded = false;
return (
<>
{!isLoaded ? (
<Skeleton className="h-24 rounded-lg" />
) : (
<div className="h-24 bg-secondary" />
)}
</>
);
}主要变化
1. 组件行为
v2: 包裹子节点,并根据 isLoaded 显示/隐藏
v3: 独立占位符——可见性由你自行控制
2. Prop 变更
| v2 prop | v3 位置 | 说明 |
|---|---|---|
isLoaded | — | 通过条件渲染手动控制可见性 |
disableAnimation | animationType | 改用 animationType="shimmer" | "pulse" | "none"(用 "none" 禁用动画) |
classNames | — | 直接使用 className prop |
children | — | Skeleton 不再包裹内容 |
3. 新增 prop
animationType—— 控制动画类型:"shimmer"(默认)、"pulse"或"none"
迁移示例
配合加载状态
import { useState } from "react";
const [isLoaded, setIsLoaded] = useState(false);
<Skeleton className="rounded-lg" isLoaded={isLoaded}>
<div className="h-24 rounded-lg bg-secondary" />
</Skeleton>import { useState } from "react";
const [isLoaded, setIsLoaded] = useState(false);
{!isLoaded ? (
<Skeleton className="h-24 rounded-lg" />
) : (
<div className="h-24 rounded-lg bg-secondary" />
)}独立 Skeleton
<div className="flex items-center gap-3">
<Skeleton className="flex rounded-full w-12 h-12" />
<div className="w-full flex flex-col gap-2">
<Skeleton className="h-3 w-3/5 rounded-lg" />
<Skeleton className="h-3 w-4/5 rounded-lg" />
</div>
</div><div className="flex items-center gap-3">
<Skeleton className="h-12 w-12 shrink-0 rounded-lg" />
<div className="flex-1 space-y-2">
<Skeleton className="h-3 w-full rounded" />
<Skeleton className="h-3 w-4/5 rounded" />
</div>
</div>动画类型
{/* Shimmer (default) */}
<Skeleton>
<div className="h-24 bg-default-300" />
</Skeleton>
{/* No animation */}
<Skeleton disableAnimation>
<div className="h-24 bg-default-300" />
</Skeleton>{/* Shimmer (default) */}
<Skeleton animationType="shimmer" className="h-24 rounded-lg" />
{/* Pulse */}
<Skeleton animationType="pulse" className="h-24 rounded-lg" />
{/* No animation */}
<Skeleton animationType="none" className="h-24 rounded-lg" />复杂示例:带内容的 Card
import { useState } from "react";
const [isLoaded, setIsLoaded] = useState(false);
<Card className="w-[200px] space-y-5 p-4" radius="lg">
<Skeleton className="rounded-lg" isLoaded={isLoaded}>
<div className="h-24 rounded-lg bg-secondary" />
</Skeleton>
<div className="space-y-3">
<Skeleton className="w-3/5 rounded-lg" isLoaded={isLoaded}>
<div className="h-3 w-full rounded-lg bg-secondary" />
</Skeleton>
<Skeleton className="w-4/5 rounded-lg" isLoaded={isLoaded}>
<div className="h-3 w-full rounded-lg bg-secondary-300" />
</Skeleton>
</div>
</Card>import { useState } from "react";
const [isLoaded, setIsLoaded] = useState(false);
<Card className="w-[250px] space-y-5 rounded-lg p-4">
{!isLoaded ? (
<>
<Skeleton className="h-32 rounded-lg" />
<div className="space-y-3">
<Skeleton className="h-3 w-3/5 rounded-lg" />
<Skeleton className="h-3 w-4/5 rounded-lg" />
</div>
</>
) : (
<>
<div className="h-32 rounded-lg bg-secondary" />
<div className="space-y-3">
<div className="h-3 w-3/5 rounded-lg bg-secondary" />
<div className="h-3 w-4/5 rounded-lg bg-secondary-300" />
</div>
</>
)}
</Card>同步的微光效果
在 v3 中,你可以创建一次性扫过所有 Skeleton 的同步微光效果。在父容器上加上 skeleton--shimmer 类,并将每个子 Skeleton 的 animationType 设为 "none":
{/* The parent container drives a single shimmer across all children */}
<div className="skeleton--shimmer space-y-4 rounded-lg p-4">
<Skeleton animationType="none" className="h-32 rounded-lg" />
<div className="space-y-3">
<Skeleton animationType="none" className="h-3 w-3/5 rounded-lg" />
<Skeleton animationType="none" className="h-3 w-4/5 rounded-lg" />
</div>
</div>这种方式适用于卡片类布局——你需要的是一次统一扫过整体的微光,而不是每个 Skeleton 各自独立地播放动画。
全局动画配置
在 v3 中,你可以通过 CSS 变量在全局设置默认的动画类型:
:root {
--skeleton-animation: pulse; /* shimmer, pulse, or none */
}各个组件上的 animationType prop 可以覆盖该默认值。
总结
- 不再包裹子节点:Skeleton 不再包裹其子节点——它本身就是一个独立的占位符
- 不再有
isLoadedprop:通过条件渲染手动控制可见性 - 动画控制:
disableAnimation→animationType("shimmer"、"pulse"、"none") - 样式:
classNames→ 直接使用classNameprop - 简化的 API:组件更简单,专注于占位符职责
- 同步微光:在父容器上使用
skeleton--shimmer类,并将子 Skeleton 的animationType设为"none",即可实现统一的微光扫过效果