如何为每个博客卡片项设置Skeleton骨架屏?现有代码失效求助
解决博客列表骨架屏实现问题
你的代码存在两个核心问题:一是加载状态依赖blogs数组,若数据未返回时blogs为空,不会渲染任何骨架屏;二是单个<Skeleton/>无法匹配BlogCard的布局结构,视觉效果割裂。以下是修正后的完整实现方案:
1. 先实现匹配BlogCard布局的骨架屏组件
先创建一个和BlogCard结构完全对应的骨架屏组件,确保占位效果和真实卡片一致:
// 自定义骨架屏组件,模拟BlogCard的布局 const BlogSkeleton = () => { return ( <div className="rounded-lg overflow-hidden bg-gray-100 animate-pulse"> {/* 模拟缩略图区域 */} <div className="h-48 bg-gray-200 w-full"></div> {/* 模拟文本内容区域 */} <div className="p-4 space-y-3"> <div className="h-6 bg-gray-200 rounded w-3/4"></div> <div className="h-4 bg-gray-200 rounded w-full"></div> <div className="h-4 bg-gray-200 rounded w-5/6"></div> <div className="flex justify-between items-center"> <div className="h-4 bg-gray-200 rounded w-20"></div> <div className="h-4 bg-gray-200 rounded w-32"></div> </div> </div> </div> ); };
如果你使用第三方UI库(如Ant Design)的Skeleton组件,可以替换成如下实现:
import { Skeleton } from 'antd'; const BlogSkeleton = () => { return ( <div className="rounded-lg overflow-hidden"> <Skeleton.Image active style={{ height: '192px' }} /> <div className="p-4"> <Skeleton.Title active width="75%" /> <Skeleton.Paragraph active rows={2} /> <div className="flex justify-between mt-3"> <Skeleton.Input active width="20%" /> <Skeleton.Input active width="30%" /> </div> </div> </div> ); };
2. 修改主列表渲染逻辑
加载状态下不再依赖blogs数组,而是生成固定数量的骨架屏(和你的网格列数匹配),确保加载时始终有占位:
<div className="grid sm:grid-cols-3 gap-[3rem]"> {loading ? ( // 渲染3个骨架屏,和sm:grid-cols-3的列数对应 Array.from({ length: 3 }).map((_, idx) => ( <BlogSkeleton key={idx} /> )) ) : ( blogs.map((blog) => ( <BlogCard key={blog.id} // 用博客唯一ID作为key,避免使用index id={blog.id} title={blog.title} thumbnail={blog.thumbnail} description={blog.description} tag={blog.tag} category={blog.category} created_at={blog.created_at} /> )) )} </div>
关键优化点
- 脱离
blogs数组依赖:加载时直接生成固定数量的骨架屏,避免数据未返回时无占位的问题 - 结构匹配:骨架屏完全模拟
BlogCard的布局,视觉过渡更自然 - 合理使用key:用博客的唯一ID替代index作为key,符合React渲染最佳实践
- 动画效果:通过
animate-pulse(Tailwind内置类)或第三方组件的active属性实现骨架屏闪烁动画,提升用户体验
内容的提问来源于stack exchange,提问作者A4Arif Dev
相关产品推荐
相关产品推荐

