# 骨架屏

骨架屏是页面的一个空白版本,通常会在页面完全渲染之前,通过一些灰色的区块大致勾勒出轮廓,待数据加载完成后,再替换成真实的内容。通常在小程序中,我们需要手工维护骨架屏的代码,当业务变更时,同样需要对骨架屏代码进行调整。为了开发的便利,开发者工具提供了自动生成骨架屏代码的能力。

# 运行环境

下载并安装 1.03.20060321.04.2006032 以上版本的开发者工具

# 使用方法

工具可以为当前正在预览的页面生成骨架屏代码。工具入口位于模拟器面板右下角三点处。

骨架屏入口

点击生成骨架屏,将有弹窗提示是否允许插入骨架屏代码。确定后将在当前页面同级目录下生成 page.skeleton.wxmlpage.skeleton.wxss 两个文件,分别为骨架屏代码的模板和样式。

提示

骨架屏代码通过小程序模板(template)的方式引入 以 pages/index/index 页面为例,引入方式如下。

<!-- pages/index/index.wxml 引入模板 -->
<import src="index.skeleton.wxml"/>
<template is="skeleton" wx:if="{{loading}}" data="{{}}"/>
/* pages/index/index.wxss 中引入样式 */
@import "index.skeleton.wxss";

示例代码:https://developers.weixin.qq.com/s/3AQoEBmh7XhF

# 显示与隐藏

与普通的模板相同,通过 wx:if 控制显示隐藏。

# 生成配置

可在 project.config.json 增加字段 skeletonConfig 进行骨架屏相关配置,页面配置会覆盖掉全局配置。

// project.config.json
{
  "skeletonConfig": {
    "global": {
      // 默认的全局配置
      "loading": "",
      "outline": {
        "remain": false,
        "replace": "none"
      },
      "text": {
        "color": "#EEEEEE"
      },
      "image": {
        "shape": "",
        "color": "#EFEFEF",
        "shapeOpposite": []
      },
      "button": {
        "color": "#EFEFEF",
        "excludes": []
      },
      "pseudo": {
        "color": "#EFEFEF",
        "shape": "circle",
        "shapeOpposite": []
      },
      "excludes": [],
      "remove": [],
      "empty": [],
      "hide": [],
      "grayBlock": [],
      "showNative": false,
      "backgroundColor": "transparent",
      "mode": "fullscreen",
      "templateName": "skeleton",
      "cssUnit": "rpx",
      "decimal": 4,
    },
    "pages": {
      "pages/index/index": {
        // 页面配置,key 为页页面路径
      }
    }
  }

具体配置如下。开发者可根据需要设置文字、图片、按钮的颜色和形状,同时可根据 excludesremovehide等忽视或隐藏部分页面元素,以获取更优的展示效果。

字段 类型 必填 默认值 说明
loading String No spin 骨架屏显示时的动画:spin chiaroscuro shine
outline Object No 该配置接受一个 remain Boolean 字段,默认为 true ,表示保持边框颜色,为 false 时,用 replace 字段替代 style.border
text Object No 该配置接受一个 color 字段,用于决定骨架页面中文字块的的颜色,颜色值支持 16 进制。
image Object No 该配置接受 3 个字段,colorshapeshapeOpposite。color 和 shape 用于确定骨架页面中图片块的颜色和形状,颜色值支持 16 进制,形状支持两个枚举值,circle (圆形)和 rect(矩形)。shapeOpposite 字段接受一个数组,数组中每个元素是一个 DOM 选择器,用于选择 DOM 元素,被选择 DOM 的形状将和配置的 shape 形状相反,例如,配置的是 rect那么,shapeOpposite 中的图片块将在骨架页面中显示成 circle 形状(圆形)
button Object No 该配置接受两个字段,colorexcludes。color 用来确定骨架页面中被视为按钮块的颜色,excludes 接受一个数组,数组中元素是 DOM 选择器,用来选择元素,该数组中的元素将不被视为按钮块
pseudo Object No 该配置接受两个字段,colorshape。color 用来确定骨架页面中被视为伪元素块的颜色,shape 用来设置伪元素块的形状,接受两个枚举值:circle 和 rect。
excludes Array No [] 如果你有不需要进行骨架处理的元素,那么将该元素的 CSS 选择器写入该数组。
remove Array No [] 不需要生成页面骨架,且需要从 DOM 中移除的元素,配置值为移除元素的 CSS 选择器。
hide Array No [] 不需要移除,但是通过设置其透明度为 0,来隐藏该元素,配置值为隐藏元素的 CSS 选择器。
empty Array No [] 该数组中元素是 CSS 选择器,被选择的元素将被清空子元素
grayBlock Array No [] 该数组中元素是 CSS 选择器,被选择的元素将被被插件处理成一个色块,色块的颜色和按钮块颜色一致。内部元素将不再做特殊处理,文字将隐藏
showNative Boolean No false 显示原生组件,为 false 时原生组件被处理为 view。
backgroundColor String No transparent 骨架屏背景色
mode String No fullscreen 默认为使用绝对定位占满全屏。当对自定义组件使用,作为局部加载的样式时,可设为 auto,高度随内容撑开
templateName String No skeleton 骨架屏模板的 name 值
cssUnit String No rpx 支持的枚举值:rpx, rem, vw, vh, vmin, vmax
decimal Number No 4 生成骨架页面中 css 值保留的小数位数,默认值是 4

原生组件包括 camera, live-player, live-pusher, video, map, canvas, picker, input, textarea

# 自定义属性

有时我们需要让骨架的某块内容显示特定的背景色,可以通过 data-skeleton-bgColor="#ff00000" 这样的方式来指定。

在处理列表的时候,为了尽可能美观,我们对列表进行了同化处理,后面的子项都是第一个子项的克隆。由于小程序的列表不是通过 ul/ol 标签来声明的,这里借助 data-* 属性进行标示。考虑到列表容器内可能插入其它结构,有如下两种声明方式:data-skeleton-list 的直接子节点将被处理成第一项的克隆;data-skeleton-li 属性相同的元素被认为是同一列表的子项。

<!-- 方式一:列表容器内容均为列表项 -->
<view wx:for="{{array}}" data-skeleton-list>
  <view class="list-item">子项内容</view>
</view>

<!-- 方式二:列表容器中插入了其它元素 -->
<view wx:for="{{array}}">
  <view class="other-block">其它</view>
  <view class="list-item" data-skeleton-li="goods">子项内容</view>
  <view class="list-item" data-skeleton-li="goods">子项内容</view>
  <view class="list-item" data-skeleton-li="goods">子项内容</view>
</view>

此外,页面可能被划分成不同的区域,通过不同的请求来获取数据,它们的响应时间也不一致。骨架屏原本是一个整体,我们希望对其进行拆分,哪条请求返回了,就替换掉对应区域的骨架屏为真实内容,达到渐进式加载的效果。声明 data-skeleton-hide 属性的节点生成骨架屏时会被替换成 hidden 属性,开发者可通过 data 控制其显示/隐藏。 需要注意的是,为了使真实数据的位置与骨架屏一致,此时应使用 absolute 方式定位页面主模块,详情参考示例 demo

<!-- 原 wxml 内容 -->
<view data-skeleton-hide="hideBlock1"></view>
<view data-skeleton-hide="hideBlock2"></view>

<!-- 骨架屏 wxml 内容 -->
<view hidden="{{hideBlock1}}"></view>
<view hidden="{{hideBlock2}}"></view>

# Tips

  1. 骨架屏仅包括页面首屏中的可见区域,对于横向滚动的 swiper 等容器,超出屏幕的子元素将被忽略;
  2. 骨架屏的布局复用开发者的页面布局,需要骨架屏自适应页面尺寸时,页面布局应采用 rpx 等自适应方案;
  3. 部分组件如 movable-viewmovable-arearich-texteditorpickerpicker-viewpicker-view-columnadofficail-accountopen-data 无法生成理想的骨架效果,可通过添加一个父容器,结合 grayBlock、empty 等配置,将其置灰。
  4. 请勿修改自动生成的骨架屏的代码,当效果不理想时,建议调整相关配置,这样当页面变更时,仍可自动生成;
  5. 生成的骨架屏代码中会包含预览时的页面数据,将被用来填充页面;
  6. 骨架屏通常用于商品列表、新闻列表等页面,对于动画/原生组件较多的页面展示效果不佳;
  7. 该能力除用于展示首屏骨架外,也可作为局部加载的 loading 样式,可灵活使用;