Element Plus Skeleton 骨架屏组件完全指南:从基础占位到防抖渲染的实战解析
Element Plus Skeleton 骨架屏组件完全指南从基础占位到防抖渲染的实战解析【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plusSkeleton骨架屏是 Element PlusVue 3 组件库中用于加载态占位的关键组件它能在数据尚未就绪时渲染出与真实界面结构近似的灰色占位骨架避免页面空白与布局跳动显著提升加载过程的视觉与交互体验。本文将基于 Element Plus 官方文档与仓库源码skeleton.md系统讲解el-skeleton与el-skeleton-item的全部属性、插槽与使用场景并深入throttle节流渲染的底层实现帮助你写出无闪烁、无跳动、体验顺滑的加载态界面。为什么需要骨架屏当页面数据尚未从服务端返回时常见的做法是展示一个全局 loading 转圈或者干脆留白。前者无法传递真实页面的结构信息后者会让用户误以为页面卡死。骨架屏的解决思路是先渲染出与真实 DOM 高度近似的灰色占位块让用户提前感知这里会有一张图片、这里有几行文字、这里有一个按钮从而降低等待焦虑。在 Element Plus 中el-skeleton提供了开箱即用的骨架屏能力支持动画、自定义模板、列表渲染、防抖切换等一系列能力接下来逐一展开。基础用法最简单的骨架屏无需任何配置直接引入组件即可el-skeleton /默认情况下会渲染出 3 行占位段落rows默认值为 3第一行宽度约为其余行的 33%起到标题行的视觉提示作用。你也可以结合template插槽与el-skeleton-item拼出圆形头像等结构。例如通过 CSS 变量--el-skeleton-circle-size控制圆形骨架的尺寸el-skeleton / br / el-skeleton style--el-skeleton-circle-size: 100px template #template el-skeleton-item variantcircle / /template /el-skeleton完整的可运行示例见 basic-usage.vue。可配置的行数rowsrows用于控制默认模板中渲染的占位段落行数el-skeleton :rows5 /需要注意文档中的一个关键细节实际渲染的行数永远比传入的rows多 1。原因在于组件内部会额外渲染一行宽度为 33% 的标题行。从 skeleton.vue 的实现可以看到默认模板由两部分组成第一个el-skeleton-itemvariantp带is-first类作为标题行随后v-for循环渲染rows个段落行最后一行带有is-last类。el-skeleton-item :classns.is(first) variantp / el-skeleton-item v-foritem in rows :keyitem :class[ns.e(paragraph), ns.is(last, item rows rows 1)] variantp /也就是说传入:rows5时页面实际看到 6 行其中首行更短、更像是标题。完整的可运行示例见 configurable-rows.vue。加载动画animated为骨架屏开启呼吸式闪烁动画只需添加animated布尔属性el-skeleton :rows5 animated /当animated为true时el-skeleton根节点会挂上is-animated类见 skeleton.vue 中的ns.is(animated, animated)所有子级骨架单元都会呈现流动的浅色渐变动画效果。该属性默认值为false。完整的可运行示例见 animation.vue。自定义模板template 插槽与 variantElement Plus 只提供了最常见的默认模板当默认结构无法满足需求时可以使用template插槽自由拼装配合el-skeleton-item的variant属性选择不同的骨架单元形态variant 取值形态说明p段落行默认值text短文本行h1一级标题样式的粗短占位h3三级标题样式的占位caption说明性小字号占位button按钮形占位image图片形占位可配合宽高样式circle圆形占位头像/图标rect矩形占位上述枚举在 skeleton-item.ts 中通过values明确限定非法值不会被接受。下面是一个仿卡片结构的自定义模板示例——上方为正方形图片占位下方为标题行与两行文字占位el-skeleton stylewidth: 240px template #template el-skeleton-item variantimage stylewidth: 240px; height: 240px / div stylepadding: 14px el-skeleton-item variantp stylewidth: 50% / div style display: flex; align-items: center; justify-items: space-between; el-skeleton-item varianttext stylemargin-right: 16px / el-skeleton-item varianttext stylewidth: 30% / /div /div /template /el-skeleton最佳实践提示构建自定义骨架结构时应尽可能让骨架的 DOM 结构与真实内容 DOM 保持接近例如占位块的高度、间距、布局层级尽量一致这样可以避免加载完成切换时因高度差导致的页面跳动DOM bouncing。完整的可运行示例见 customized-template.vue。加载状态切换loading 与 default 插槽数据加载完成后需要把骨架屏切换回真实界面。通过loading属性默认true控制显示哪一侧并通过default插槽放置真实 DOMel-space directionvertical alignmentflex-start div label stylemargin-right: 16pxSwitch Loading/label el-switch v-modelloading / /div el-skeleton stylewidth: 240px :loadingloading animated template #template el-skeleton-item variantimage stylewidth: 240px; height: 240px / div stylepadding: 14px el-skeleton-item varianth3 stylewidth: 50% / div style display: flex; align-items: center; justify-items: space-between; margin-top: 16px; height: 16px; el-skeleton-item varianttext stylemargin-right: 16px / el-skeleton-item varianttext stylewidth: 30% / /div /div /template template #default !-- 加载完成后的真实内容如 el-card、图片、按钮等 -- /template /el-skeleton /el-space从源码实现看loading会经过useThrottleRender的节流处理后形成内部状态uiLoading见 skeleton.vue模板根据uiLoading决定渲染骨架层还是default插槽内容。完整的可运行示例见 loading-state.vue。渲染数据列表count骨架屏最常见的应用场景是列表数据加载中的占位。count属性用于控制同一套模板重复渲染的次数从而凭空生成多条骨架项让列表看起来正在加载el-skeleton styledisplay: flex; gap: 8px :loadingloading animated :count3 template #template div styleflex: 1 el-skeleton-item variantimage styleheight: 240px / div stylepadding: 14px el-skeleton-item varianth3 stylewidth: 50% / div style display: flex; align-items: center; justify-items: space-between; margin-top: 16px; height: 16px; el-skeleton-item varianttext stylemargin-right: 16px / el-skeleton-item varianttext stylewidth: 30% / /div /div /div /template template #default !-- v-for 渲染真实列表数据 -- /template /el-skeleton真实数据到达后把loading置为false并传入列表数据骨架即可无缝切换为真实卡片。完整的可运行示例见 rendering-with-data.vue。::: tip 性能建议 官方文档明确提示不建议向浏览器渲染大量虚假 UI。过多的骨架项同样会造成性能问题且销毁骨架也需要更长时间。请让count尽可能小以获得更好的用户体验。 :::避免渲染跳动throttle 节流当接口响应极快时骨架屏刚渲染出来就要立刻切回真实 DOM会出现一瞬的闪烁flash观感很差。为此el-skeleton提供了throttle属性以毫秒为单位延迟骨架屏的显示给快速返回的数据留出缓冲窗口el-skeleton stylewidth: 240px :loadingloading animated :throttle500 !-- template 与 default 插槽同上 -- /el-skeletonthrottle 的两种取值形式^2.8.8从 2.8.8 版本起throttle支持number和object两种形式传入数字时等价于{ leading: xxx }即控制骨架屏显示前的延迟传入对象{ trailing: xxx }时可进一步控制骨架屏消失隐藏前的延迟。完整的可运行示例见 avoiding-rendering-bouncing.vue。初始加载即显示{ initVal: true }^2.8.8当loading的初始值为true时如果直接设置throttle: 500骨架屏也会被节流延迟显示导致页面一开始没有骨架也没有内容。此时可以传入{ initVal: true, leading: xxx }让初始骨架屏立即显示、不受节流影响el-skeleton stylewidth: 240px :loadingloading animated :throttle{ leading: 500, initVal: true } !-- ... -- /el-skeleton完整的可运行示例见 initial-rendering-loading.vue。平滑切换{ leading, trailing, initVal }^2.8.8当loading在true/false之间反复切换时可以同时指定leading与trailing让骨架屏的出现与消失都经过节流缓冲从而避免切换过程中的渲染跳动rendering bouncingel-skeleton stylewidth: 240px :loadingloading animated :throttle{ leading: 500, trailing: 500, initVal: true } !-- ... -- /el-skeleton这样配置后初始骨架立即显示之后每次切到加载态延迟 500ms 才出现骨架每次切回真实内容也延迟 500ms切换过程更平滑。完整的可运行示例见 leading-trailing-without-bouncing.vue。throttle 的底层实现原理throttle的节流逻辑并不在el-skeleton内部实现而是复用 Element Plus 的useThrottleRenderHook源码见 use-throttle-render/index.ts。其核心思路如下export type ThrottleType { leading?: number; trailing?: number; initVal?: boolean } | number export const useThrottleRender ( loading: Refboolean, throttle: ThrottleType 0 ) { if (throttle 0) return loading const initVal isObject(throttle) Boolean(throttle.initVal) const throttled ref(initVal) // ... 通过 watch setTimeout 分别处理 leading / trailing 延迟 }关键点throttle为 0 时直接透传不引入任何延迟此时组件表现等同无节流initVal决定初始状态当loading初始为true且设置了initVal: true内部节流状态的初始值即为true骨架屏首帧就显示绕开leading的延迟leading/trailing分别挂钩显示与隐藏通过watch监听loading变化配合setTimeout延后更新内部状态从而达成延迟出现 / 延迟消失的双向节流。在 skeleton.vue 中useThrottleRender(toRef(props, loading), props.throttle)的返回值被命名为uiLoading模板只认这个节流后的状态——这就是节流切换无闪烁的实现基础。同时uiLoading也通过defineExpose暴露给外部方便在特殊场景下直接读取当前骨架屏的显示状态。Skeleton API 速查Skeleton Attributes名称说明类型默认值animated是否显示加载动画^[boolean]falsecount渲染到 DOM 中的骨架项数量^[number]1loading是否显示真实 DOMfalse时渲染default插槽内容^[boolean]truerows行数仅在没有提供template插槽时生效实际渲染行数会比该值多 1多出的为首行 33% 宽标题行^[number]3throttle渲染延迟毫秒。数字表示延迟显示也可传入对象延迟隐藏如{ leading: 500, trailing: 500 }需要控制loading初始值时设置{ initVal: true }^[number] / ^[object]{ leading?: number, trailing?: number, initVal?: boolean }0需要说明的是源码 skeleton.ts 中loading的 prop 默认值即为true文档表格中写作false的默认值实际上被useThrottleRender与组件内部状态共同决定实践中以不传loading时默认显示骨架屏为准。Skeleton Slots名称说明插槽参数default真实渲染 DOM加载完成后的内容^[object]$attrstemplate骨架屏模板内容^[object]{ key: number }循环渲染时的序号SkeletonItem APISkeletonItem Attributes名称说明类型默认值variant当前渲染的骨架单元类型^[enum]p \| text \| h1 \| h3 \| caption \| button \| image \| circle \| recttextel-skeleton-item的类型定义位于 skeleton-item.ts其variant枚举与样式类一一对应对应的 SCSS 样式可在 theme-chalk/src/skeleton-item.scss 中查看每种变体的尺寸与圆角规则。实战小结综合文档与源码使用el-skeleton时可以遵循以下原则静态占位直接使用rows 默认模板或通过template插槽 el-skeleton-item的variant拼装与真实 DOM 近似的结构数据列表用count生成多条占位配合v-for渲染的真实列表切换交互体验animated开启动画用throttlenumber或{ leading, trailing, initVal }消除快速响应下的闪烁与切换跳动性能控制count大小避免一次性渲染过多假 UI。通过loading属性与default插槽的组合el-skeleton将加载占位与真实内容统一封装在一个组件里再配合useThrottleRender的节流机制即可低成本地构建出专业、顺滑、无跳动的加载态界面。【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考