☰
Shimmer From Structure templateProps 详解:让动态数据组件也拥有像素级骨架屏
2026/10/15 15:10:43 网站建设 项目流程

【免费下载链接】shimmer-from-structure

A structure-aware skeleton loader that mirrors your rendered UI at runtime. Zero layout duplication. Built for modern frameworks.

项目地址:https://gitcode.com/gh_mirrors/sh/shimmer-from-structure
点击查看免费下载

如果你正在使用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 个步骤

理解内部流程,你会对这个库更有信心。整个过程在加载期间自动完成:

  1. 渲染测量容器:loading={true}时,你的组件会渲染进一个测量容器,文字被设为透明(color: transparent),但卡片背景、边框等容器样式保留可见——所以你的骨架屏自带真实 UI 的"底色"
  2. 模板数据注入:如果提供了templateProps,克隆首个子元素并展开注入,动态组件得以带着 mock 数据渲染
  3. 同步 DOM 测量:React 版用useLayoutEffect(浏览器绘制前同步执行,杜绝闪烁),对每个叶子元素调用getBoundingClientRect()获取精确坐标与尺寸,核心测量函数在 packages/core/src/extractElementInfo.ts
  4. 圆角检测 + 渐变动画:自动捕获每个元素的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.

项目地址:https://gitcode.com/gh_mirrors/sh/shimmer-from-structure
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询