首先了解下什么是骨架屏?
骨架屏就是在页面数据尚未加载前先给用户展示出页面的大致结构,直到请求数据返回后再渲染页面,补充进需要显示的数据内容。常用于文章列表、动态列表页等相对比较规则的列表页面。 很多项目中都有应用饿了么h5版本,知乎,facebook等网站中都有应用。
以下图举例,常用饿了么的童鞋,应该看到过饿了么的这个首页预加载图的效果:
咱们来聊聊小程序的实现方案:
1.最简单最快捷最暴力的,直接让设计一张图片盖上去,当loading使用。
举例:饿了么的订单页面,查看了下源码,是使用的SVG的图
2.前端使用view写死一套数据(缺点很明显,假如页面布局有修改的话,那么除了修改业务代码之外还需要额外修改骨架屏,增加了维护的成本)
举例:简单写了个微信小程序的代码片段(支付宝暂无代码片段功能):https://developers.weixin.qq.com/s/ZAuYzHmX7ObC
3.页面Data里写死一套默认数据,使用小程序的my.createSelectorQuery().selectAll 选择了所有要渲染的矩形和圆形节点,在页面中,使用循环,遍历出所有的节点,再加上样式。
首先来看 如何操作:
使用my.createSelectorQuery 获取到相关节点进行渲染操作,但是我们把默认数据这一栏更改为动态数据。
核心代码就是自定义组件内抛出的isNodes和isComplete属性
//axml <skeletons isNodes="{{isNodes}}" isComplete="{{isComplete}}"" /> //页面节点上需要手动添加一个样式类。 比如轮播图 宽686rpx,高140rox,是长方形那么给他的样式上加上‘skeletions-rect’,如果是圆形给他加上‘skeletons-circle’
业务内代码如下:
<!-- 轮播图组件 --> <block a:if="{{swiperData.length > 0}}"> <swiper class="swiperSlide" indicator-dots="{{indicatorDots}}" indicator-color="#ccc" indicator-active-color="#00CC88" autoplay circular> <block a:for="{{swiperData}}" a:key="{{index}}"> <swiper-item> <view class="swiper-item"> <image lazy-load src="{{item.image}}" data-index="{{index}}" onTap="universalJump" class="skeletons-rect" /> </view> </swiper-item> </block> </swiper> <!-- <qts-swiper resourseFrom="{{swiperData}}" indicatorDots="{{indicatorDots}}"></qts-swiper> --> </block>
相关JS如下:
initData() { let postData = { townId: util.getStorageSync('townId') || 87 } // 初始化请求 app.postAjax('https://url.com', postData).then((res) => { if (res.success) { this.setData({ bodyData: res.data, //页面展示数据的大对象 isNodes: true //抓取节点绘制骨架屏 }, () => { this.setData({ isComplete: true //节点绘制完成,隐藏骨架屏 }) }) } else { util.toast(res.msg || '团团开小差啦,请稍后重试') } }, () => { util.toast('团团开小差啦,请稍后重试') }) },
在微信端的难题:组件之间无法样式穿透的问题(A组件通过index页面影响B组件的样式),在支付宝端完美不存在,算是解决了一个大问题吧。
最后完整组件代码地址:https://gitee.com/minchangyong/skeletons