【免费下载链接】shimmer-from-structure
A structure-aware skeleton loader that mirrors your rendered UI at runtime. Zero layout duplication. Built for modern frameworks.
如果你正在使用Shimmer From Structure这个结构感知型骨架屏(skeleton loader)库,大概率遇到过这样的尴尬:静态内容组件一行代码就能生成完美的闪烁占位,但依赖 props 传入数据的动态组件,在user还是null时根本渲染不出内容,骨架屏自然也就无从"测量"。templateProps正是为了解决这个问题而生的——只需提供一份模拟数据(mock data),骨架屏就能按照你真实组件的像素级布局生成,加载完成瞬间无缝切换,完全零布局抖动。
痛点:为什么动态组件的骨架屏这么难写
传统骨架屏方案要求你为每个组件手写一份"孪生"骨架组件:头像占位圆、文字占位条、列表占位行……代价是:
- 每个组件要维护两份代码(真实 + 骨架),改一次布局要改两次
- 骨架组件和真实组件迟早会失同步——加个字段,骨架忘了加
- 动态数据组件更麻烦:数据没到之前,组件渲染为空,手写的骨架和真实布局往往是"两张皮"
Shimmer From Structure 的思路完全不同:运行时直接测量你渲染出来的真实 DOM(尺寸、位置、圆角),然后生成与之一一对应的闪烁块。但对动态组件来说,"真实 DOM"在数据到达前是空的,测量不到任何东西——这就是templateProps登场的时刻。
templateProps 是什么:一行 mock 数据,骨架屏立即可用
templateProps是<Shimmer>组件的一个可选属性,类型为Record<string, unknown>,作用是在加载期间把模拟数据注入到子组件,让组件带着"假数据"正常渲染一遍,供库测量布局。
以 React 为例,只需三步:
// 1. 定义一份模拟数据(结构与真实数据一致) const userTemplate = { name: 'Loading...', role: 'Loading role...', avatar: 'placeholder.jpg', }; // 2. 传给 Shimmer <Shimmer loading={loading} templateProps={{ user: userTemplate }}> <UserCard user={user || userTemplate} /> </Shimmer>注意这里有个精妙的设计:templateProps会被展开(spread)到第一个子组件上。加载期间,库克隆第一个子元素并注入{ ...templateProps },子组件收到的不是null而是模板数据,于是完整渲染出头像、标题、描述等 DOM 结构;库同步测量这些元素的精确位置、尺寸与 CSS 圆角,生成像素级一致的闪烁块。当loading变为false,真实数据替换 mock 数据,布局结构相同,切换零闪烁。
注入逻辑可以见 packages/react/src/Shimmer.tsx,核心就是React.cloneElement(firstChild, { ...templateProps })这一行——简单、可预期。
工作原理:从数据注入到像素级闪烁的 4 个步骤
理解内部流程,你会对这个库更有信心。整个过程在加载期间自动完成:
- 渲染测量容器:
loading={true}时,你的组件会渲染进一个测量容器,文字被设为透明(color: transparent),但卡片背景、边框等容器样式保留可见——所以你的骨架屏自带真实 UI 的"底色" - 模板数据注入:如果提供了
templateProps,克隆首个子元素并展开注入,动态组件得以带着 mock 数据渲染 - 同步 DOM 测量:React 版用
useLayoutEffect(浏览器绘制前同步执行,杜绝闪烁),对每个叶子元素调用getBoundingClientRect()获取精确坐标与尺寸,核心测量函数在 packages/core/src/extractElementInfo.ts - 圆角检测 + 渐变动画:自动捕获每个元素的
border-radius——圆形头像自动得到圆形闪烁块;没有圆角的文本元素用fallbackBorderRadius兜底,避免生硬的直角矩形。最后叠加横扫的渐变光效
五大框架的 templateProps 支持一览
这是一个 monorepo 项目,React、Vue、Svelte、Angular、SolidJS 各有适配器,templateProps的落地方式略有差异:
| 框架 | 注入方式 | 说明 |
|---|---|---|
| React | 自动展开到首个子组件 | cloneElement注入,最"魔法"的方式 |
| Vue 3 | 透传给<slot> | 模板内v-bind="templateProps",见 Shimmer.vue |
| Svelte | 参数保留,官方推荐显式条件 | 类型定义中标注"将在未来版本移除"(types.ts),惯用法是contextData \|\| template |
| Angular | 模板内显式条件 | 惯用法是[user]="user() \|\| userTemplate"绑定 |
| SolidJS | 参数保留,官方推荐显式条件 | 源码注释说明:user() \|\| template更类型安全,参数仅为跨框架 API 一致(Shimmer.tsx) |
💡一个值得注意的统一模式:无论哪个框架,最佳实践都是在子组件上写真实数据 || 模板数据的兜底。React/Vue 中它保证渲染兜底;Svelte/Angular/Solid 中它就是主要手段。这个模式让所有框架的行为完全一致,也让你随时可以手动控制模板内容。
实战 3 个技巧:让骨架屏与真实数据"严丝合缝"
官方 Best Practices 文档 总结的三条黄金法则:
技巧 1:模板结构与真实数据严格对齐🎯 真实接口返回 5 条交易记录,模板数据就写 5 条(哪怕全是Loading...占位文案)。数组长度、字段结构一致,加载完成时才不会发生布局跳动。参考 examples/react-example/src/main.tsx 里userTemplate、transactionsTemplate的完整写法——它模拟了一个真实 Dashboard,每个区域的模板都与真实数据一一对应。
技巧 2:每个区域包独立的<Shimmer>⚡ 用户信息 800ms 返回、订单列表 2s 返回?给每个区域独立的loading状态和独立的<Shimmer>,谁先加载完谁先显示,而不是"全有或全无"。示例代码里 7 个区域各自独立加载,体验非常流畅。
技巧 3:异步组件要给容器明确的宽高📏 图表这类异步渲染的组件本身没有初始尺寸,测量会落空。给它套一层带明确width/height的容器(如height: 250px),骨架屏立刻有物可测。
快速上手与延伸阅读
安装只需要一条命令:
npm install shimmer-from-structure各框架的导入方式(Vue 用@shimmer-from-structure/vue、Angular 用@shimmer-from-structure/angular等)可以在 README.md 的 Framework Support 一节查到。
更多资料推荐:
templateProps完整属性表与全框架示例:docs/app/docs/api/page.tsx- 设计决策与"只注入首个子组件"的原因:docs/app/docs/how-this-works/page.tsx
- 真实 Dashboard 完整示例(含 React Suspense 集成):examples/react-example/src/main.tsx
总结:templateProps用一份 mock 数据,就让"数据没到"的动态组件也能渲染出完整结构,让骨架屏从"手写两遍"变成"零维护"。模板数据写得越贴近真实数据,你的骨架屏就越接近真实 UI 的像素级还原——这就是 Shimmer From Structure 名字里 "from structure" 的深意。
【免费下载链接】shimmer-from-structure
A structure-aware skeleton loader that mirrors your rendered UI at runtime. Zero layout duplication. Built for modern frameworks.
相关推荐
7个SkeletonView高级特性:打造动态响应式骨架屏的完整指南
7个SkeletonView高级特性:打造动态响应式骨架屏的完整指南 SkeletonView是一款优雅的iOS开发框架,能够为应用提供精美的骨架屏加载效果,让
UI库/组件终极Windows风扇控制指南:如何使用FanControl实现精准温控与静音优化
终极Windows风扇控制指南:如何使用FanControl实现精准温控与静音优化 前言:你是否厌倦了电脑风扇的噪音问题?当CPU温度飙升时,风扇突然全速运转的
桌面应用智能硬件boneyard:从真实 UI 自动提取像素级骨架屏的跨框架方案
boneyard:从真实 UI 自动提取像素级骨架屏的跨框架方案 boneyard 是一套自动生成骨架屏(skeleton loading screen)的工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考