- 前端
- UI组件
- 跨平台
【免费下载链接】quasar
Quasar Framework - Build high-performance VueJS user interfaces in record time
QSkeleton 是 Quasar Framework 提供的占位预览组件,用于在真实数据加载完成前,向用户展示内容结构的"骨架"轮廓,从而提升页面的感知性能。本文基于 Quasar 官方文档与仓库源码,系统讲解 QSkeleton 的预定义类型、动画、尺寸与样式控制,并给出可直接复用的实战配方(模拟 YouTube、Facebook、Twitter、Twitch、表格与列表),帮助你快速掌握骨架屏在 Quasar 应用中的落地技巧。
什么是 QSkeleton
QSkeleton 是一个用于在加载真实页面数据之前,展示内容占位预览的 Vue 组件。它向用户预先传递"页面将要长什么样"的信息,在数据尚未完全到达时以渐进方式渲染屏幕内容,从而显著提升感知性能(perceived performance)。它经常与 QInnerLoading、QCircularProgress、QSpinner 以及 Loading、LoadingBar 等加载相关能力搭配使用。
在仓库中,QSkeleton 的完整实现位于 QSkeleton.js,样式定义在 QSkeleton.sass,并通过 components.js 注册为 Quasar 全局组件,因此可以直接在模板中书写<q-skeleton>。
基础用法:在 QCard 中搭建卡片骨架
最常见的场景是用 QSkeleton 模拟一张卡片的结构。官方文档的入门示例(Card.vue)将头像、文本、大图和按钮组合成一个完整的卡片骨架:
<template> <div class="q-pa-md"> <q-card style="max-width: 300px"> <q-item> <q-item-section avatar> <q-skeleton type="QAvatar" /> </q-item-section> <q-item-section> <q-item-label> <q-skeleton type="text" /> </q-item-label> <q-item-label caption> <q-skeleton type="text" /> </q-item-label> </q-item-section> </q-item> <q-skeleton height="200px" square /> <q-card-actions align="right" class="q-gutter-md"> <q-skeleton type="QBtn" /> <q-skeleton type="QBtn" /> </q-card-actions> </q-card> </div> </template>这段代码展示了 QSkeleton 的核心用法:每种内容形态用对应type的骨架块占位,再配合height、square等属性微调细节。默认情况下 QSkeleton 的动画为wave,用户看到的是一个带有流动光效的占位轮廓。
预定义类型
QSkeleton 提供了三类基本形状与多种"便捷类型"。从源码 QSkeleton.js 可以看到,type属性的合法值由skeletonTypes数组校验:
export const skeletonTypes = [ 'text', 'rect', 'circle', 'QBtn', 'QBadge', 'QChip', 'QToolbar', 'QCheckbox', 'QRadio', 'QToggle', 'QSlider', 'QRange', 'QInput', 'QAvatar' ]- 基本类型:
text(文本行,默认被垂直压缩为一半高度,模拟文字行)、rect(矩形,也是组件默认值)、circle(圆形)。 - 便捷类型:以 Quasar 组件命名的类型会精确匹配对应组件的尺寸与圆角,例如
QBtn、QBadge、QChip、QToolbar、QCheckbox、QRadio、QToggle、QSlider、QRange、QInput、QAvatar。这些类型的默认尺寸定义在 QSkeleton.sass 中,例如QBtn为 90×36px、QChip为 90×28px 且圆角 16px、QAvatar/circle为 48×48px 且圆角 50%、QInput高 56px、QToolbar高 50px、QToggle为 56×40px 圆角 7px、QCheckbox/QRadio为 40×40px 圆形。
文档示例(Types.vue)遍历全部 14 种类型,每种类型放在一张卡片中渲染。注意type属性带有 validator 校验,传入未定义的类型会在开发环境得到警告。
动画
QSkeleton 内置 7 种动画,源码中的skeletonAnimations数组(QSkeleton.js)定义了合法值:
export const skeletonAnimations = [ 'wave', 'pulse', 'pulse-x', 'pulse-y', 'fade', 'blink', 'none' ]| 动画值 | 效果 | 底层实现(QSkeleton.sass) |
|---|---|---|
wave(默认) | 一道高光从左侧划过,模拟"水波"扫过 | 通过:after伪元素叠加白色渐变,执行q-skeleton--wave的 translateX 位移动画 |
pulse | 整体缩放呼吸(scale 1 → 0.85) | q-skeleton--pulsekeyframes |
pulse-x | 仅横向缩放(scaleX 1 → 0.75) | q-skeleton--pulse-xkeyframes |
pulse-y | 仅纵向缩放(scaleY 1 → 0.75) | q-skeleton--pulse-ykeyframes |
fade | 透明度 1 → 0.4 循环渐变 | q-skeleton--fadekeyframes |
blink | 白色遮罩整体淡入淡出,模拟闪烁 | :after叠加半透明白色遮罩并复用 fade 动画 |
none | 无动画 | 组件不会添加q-skeleton--anim类,参见 QSkeleton.js |
wave、blink(以及源码中预留的pop)类动画都依赖:after伪元素,因此会为元素设置position: relative; overflow: hidden; z-index: 1。所有动画的时长由 CSS 变量--q-skeleton-speed控制,默认 1500ms(在 QSkeleton.sass 中定义)。
animation:String 类型,默认'wave',接受上表任意值,有 validator 校验。animation-speed:String 或 Number 类型,默认1500(毫秒)。组件会将它写成内联 CSS 变量--q-skeleton-speed: 1500ms(见 QSkeleton.js),因此设置animation-speed="750"即可让动画快一倍。这一行为在 QSkeleton.test.js 中有测试覆盖。
文档示例(Animations.vue)遍历全部动画值逐一展示。测试用例 QSkeleton.test.js 也验证了:animation="none"时不会出现q-skeleton--anim类,其余动画都会追加对应的q-skeleton--anim-{name}类。
尺寸控制
QSkeleton 提供三个尺寸相关属性(Sizing.vue 展示了典型用法):
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
size | String | — | 同时设置宽和高(正方形占位) |
width | String | — | 单独设置宽度 |
height | String | — | 单独设置高度 |
从源码(QSkeleton.js)可以看到其优先级逻辑:当size有值时,宽高都取size;否则分别取width与height,最终以内联样式输出。另外,QSkeleton.sass 为组件设置了box-sizing: border-box,确保加上边框后尺寸不会膨胀。
<q-skeleton type="circle" size="100px" /> <q-skeleton width="150px" /> <q-skeleton height="150px" /> <q-skeleton size="50px" /> <q-skeleton width="200px" height="100px" />样式定制
Bordered(带边框)
bordered布尔属性为骨架添加 1px 细边框(浅色主题为rgba(0,0,0,.05),见 QSkeleton.sass),让占位块轮廓更清晰。示例 StylingBordered.vue:
<q-skeleton bordered type="circle" /> <q-skeleton bordered /> <q-skeleton bordered square />Square(直角)
square布尔属性把圆角重置为 0(border-radius: 0,见 QSkeleton.sass),适合卡片头部横幅、媒体区等直角场景。示例 StylingSquare.vue。
自定义颜色
QSkeleton 的基础背景色使用 Quasar 的$separator-color(分隔线色),深色模式下自动切换为rgba(255,255,255,.05)(见 QSkeleton.sass)。你可以直接复用 Quasar 的颜色工具类覆盖背景色,示例 StylingColor.vue:
<q-skeleton class="bg-accent" type="circle" /> <q-skeleton class="bg-teal" /> <q-skeleton class="bg-orange" animation="pulse-y" /> <q-skeleton class="bg-indigo" />自定义边框与圆角
占位块本身就是普通元素,完全可以通过自定义 CSS 覆盖样式。示例 StylingCustomBorder.vue 展示了如何用 SASS 类同时改写圆角和边框颜色:
<template> <div class="q-pa-md"> <q-skeleton width="100px" height="50px" class="custom-skeleton-border" /> </div> </template> <style lang="sass"> .custom-skeleton-border border-radius: 10px 0 24px 4px border: 1px solid #aaa </style>深色模式(dark)
QSkeleton 通过 Quasar 的useDarkcomposable 自动感知深色模式(QSkeleton.js),渲染时添加q-skeleton--dark或q-skeleton--light类。深色主题下背景、边框和 wave/blink 动画遮罩都会自动使用更柔和的白色透明值(见 QSkeleton.sass),无需额外处理即可适配暗色 UI。
实战配方(Recipes)
文档提供了 6 组精心编排的"配方"示例,可以直接拷贝进项目按需改造:
模拟 YouTube 卡片
来自 RecipeYoutube.vue:顶部 150px 高的直角媒体区,下方叠加标题行与两行副标题文本,并用width="50%"制造长短不一的自然观感:
<q-card flat style="max-width: 300px"> <q-skeleton height="150px" square /> <q-card-section> <q-skeleton type="text" class="text-subtitle1" /> <q-skeleton type="text" width="50%" class="text-subtitle1" /> <q-skeleton type="text" class="text-caption" /> </q-card-section> </q-card>模拟 Facebook 动态
来自 RecipeFacebook.vue:头像 + 标题 + 200px 媒体区 + 正文行,整组统一使用animation="fade"营造更安静的加载氛围:
<q-card flat bordered style="max-width: 300px"> <q-item> <q-item-section avatar> <q-skeleton type="QAvatar" animation="fade" /> </q-item-section> <q-item-section> <q-item-label><q-skeleton type="text" animation="fade" /></q-item-label> <q-item-label caption><q-skeleton type="text" animation="fade" /></q-item-label> </q-item-section> </q-item> <q-skeleton height="200px" square animation="fade" /> <q-card-section> <q-skeleton type="text" class="text-subtitle2" animation="fade" /> <q-skeleton type="text" width="50%" class="text-subtitle2" animation="fade" /> </q-card-section> </q-card>模拟 Twitter 推文
来自 RecipeTwitter.vue:头像 + 文本行 + 150px 配图 + 一排操作按钮(评论、转发、点赞),操作按钮用灰色QIcon加 30px 宽的文本骨架模拟图标与计数。
模拟 Twitch 直播间
来自 RecipeTwitch.vue:170px 视频区 + 56px 方形头像 + 三行文本,全部使用square直角与animation="fade",并通过height="12px"、width="75%"精细控制文本行高度与宽度。
模拟数据表格
来自 RecipeTable.vue:在QMarkupTable中,表头 6 列使用animation="blink" type="text"的骨架,表体用v-for="n in 5"循环渲染 5 行、每列宽度各异的骨架文本(85px、50px、35px…),是最贴合后台管理页的表格加载方案。
模拟列表
来自 RecipeList.vue:三条QItem均由QAvatar圆头像加两行文本组成,第二行文本宽度依次为 65%、90%、35%,形成错落有致的列表观感。
无障碍(Accessibility)
自 v2.25 起,官方文档明确了 QSkeleton 的无障碍定位:它只是一个装饰性占位,本身不携带任何 ARIA 语义——屏幕阅读器扫过骨架屏时只会看到一堆空的、未标记的盒子。
因此推荐两种处理方式:
- 对骨架屏容器设置
aria-hidden="true",让辅助技术直接忽略它; - 或者对加载区域本身设置
aria-busy="true",向辅助技术传达"该区域尚未就绪"的状态,待真实内容渲染后移除该属性。
同时,从源码(QSkeleton.js)可以看出,组件把默认插槽内容通过hSlot渲染出来,因此你可以在骨架内部放入兜底内容;再加上渲染时q-skeleton--anim类会设置cursor: wait(QSkeleton.sass),向鼠标用户传递"正在加载"的视觉提示。
与加载相关组件的配合
QSkeleton 常与 Quasar 的其他加载能力组合使用:数据到达前先用骨架屏撑起布局,请求过程中用 QInnerLoading 或 QSpinner 表达局部忙碌,全局进度可用 Loading 插件或顶部的 LoadingBar;对于圆形区域,也可以考虑 QCircularProgress 的 indeterminate 模式。骨架屏负责"告知用户内容结构",其余组件负责"告知用户加载进度",两者互补。
小结
QSkeleton 是一个零依赖、纯 CSS + Vue 渲染的轻量组件:14 种预定义类型、7 种动画、3 个尺寸属性与square/bordered/dark开关构成了完整的占位能力,配合自定义类即可覆盖任意视觉需求。其实现细节(类型与动画的校验数组、--q-skeleton-speed变量、box-sizing: border-box的尺寸策略、深浅色双主题)均可分别在 QSkeleton.js、QSkeleton.sass 与 QSkeleton.test.js 中查阅验证。在接入真实数据时,配合v-if/v-else在骨架与真实内容间切换,即可用极少的代码获得流畅的加载体验。
- 前端
- UI组件
- 跨平台
【免费下载链接】quasar
Quasar Framework - Build high-performance VueJS user interfaces in record time
相关推荐
终极指南:ZK Bug Tracker如何成为零知识证明安全的守护者
终极指南:ZK Bug Tracker如何成为零知识证明安全的守护者 ZK Bug Tracker作为社区维护的零知识证明(ZK)安全漏洞数据库,是开发者、审计
LovyanGFX高级应用:EPD电子纸与HUB75 LED屏驱动实战
LovyanGFX高级应用:EPD电子纸与HUB75 LED屏驱动实战 LovyanGFX是一款专为ESP32、ESP8266等嵌入式设备设计的高性能SPI L
嵌入式图形学Hyperapp视图与组件设计:条件渲染、key与组件拆分的6个最佳实践
Hyperapp视图与组件设计:条件渲染、key与组件拆分的6个最佳实践 Hyperapp 是一个仅约 1kB 的 JavaScript 框架,用于构建超文本应
前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考